Spring Security - Retaining URL parameters on redirect to login

后端 未结 4 836
攒了一身酷
攒了一身酷 2020-12-08 20:23

ok.

lets say I have a secure url pattern

/secure/link-profile

optionally, there can be url paramaters appended.

/se         


        
相关标签:
4条回答
  • 2020-12-08 21:02

    as per @zagyi's response I just overrode a method in my existing extension of AuthenticationProcessingFilterEntryPoint

    the method to override is protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) which is called by buildRedirectUrlToLoginPage(..

    @Override
    protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException exception) {
        String url = super.determineUrlToUseForThisRequest(request, response, exception);
        return url + "?" + request.getQueryString();
    }
    

    obviously that could be improved to also use a builder of sorts, catering for an existing query string on the url, but at this time I know my login url is always /login/, so this is fine for my purposes

    0 讨论(0)
  • 2020-12-08 21:04

    See the method buildRedirectUrlToLoginPage(HttpServletRequest request, ...) in LoginUrlAuthenticationEntryPoint.

    If I understood correctly what you want to achieve, I think it should be enough to override this method in a sublclass, copy the original method, but additionally call urlBuilder.setQuery(request.getQueryString()) when it builds the url.

    Then you only need to configure the ExceptionTranslationFilter with this customized entry point.

    0 讨论(0)
  • 2020-12-08 21:15

    A different article explains how overriding does not work. I needed to override commence. This may perhaps be a new thing that was introduced in later versions of spring security.

    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        protected void configure(final HttpSecurity httpSecurity) throws Exception {
        httpSecurity.
        formLogin().loginPage("/signIn").permitAll().
            and().
                authorizeRequests().
                antMatchers(managementContextPath + "/**").permitAll().
                anyRequest().authenticated().withObjectPostProcessor(objectPostProcessor).
            and().
                csrf().disable().
                contentTypeOptions().
                xssProtection().
                cacheControl().
                httpStrictTransportSecurity().
            and().
                requestCache().requestCache(new RedisRequestCache(savedRequestRedisTemplate())).
            and().
                sessionManagement().sessionAuthenticationStrategy(sessionAuthenticationStrategy).
            and().
                exceptionHandling().authenticationEntryPoint(new AuthenticationProcessingFilterEntryPoint("/signIn"));
        }
    }
    
    public class AuthenticationProcessingFilterEntryPoint extends LoginUrlAuthenticationEntryPoint {
        public AuthenticationProcessingFilterEntryPoint(String loginFormUrl) {
            super(loginFormUrl);
        }
    
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
            RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
            redirectStrategy.sendRedirect(request, response, getLoginFormUrl() + "?" + request.getQueryString());
        }
    }
    

    Rizier123, thanks again for your pointers.

    0 讨论(0)
  • 2020-12-08 21:17

    Hi kabal -

    I have very similar requirements, and I followed yours and zagyi's and lion's post, but I still seem to loose the original request parameter on /login page.

    Here's what I have:

    public class AuthenticationProcessingFilterEntryPoint extends LoginUrlAuthenticationEntryPoint {
        @Override
        protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) {
            String url = super.determineUrlToUseForThisRequest(request, response, exception);
            return url + "?" + request.getQueryString();
        }
    }
    
    
    
    protected void configure(final HttpSecurity httpSecurity) throws Exception {
        httpSecurity.
        formLogin().loginPage("/signIn").permitAll().
            and().
                authorizeRequests().
                antMatchers(managementContextPath + "/**").permitAll().
                anyRequest().authenticated().withObjectPostProcessor(objectPostProcessor).
            and().
                csrf().disable().
                contentTypeOptions().
                xssProtection().
                cacheControl().
                httpStrictTransportSecurity().
            and().
                requestCache().requestCache(new RedisRequestCache(savedRequestRedisTemplate())).
            and().
                sessionManagement().sessionAuthenticationStrategy(sessionAuthenticationStrategy).
            and().
                addFilter(new ExceptionTranslationFilter(new AuthenticationProcessingFilterEntryPoint()));
    }
    

    I can see that AuthenticationProcessingFilterEntryPoint is deployed, but it does not hit a breakpoint there.

    Based on the documentation, it appears that this will kick in only when there is AuthenticationException or AccessDeniedException. In the configuration above, I am not sure if the spring internally throws such exception when such happens.

    Additionally, I'd like to to preserve the query parameter on the landing page regardless authentication succeeds or not.

    I did add success and failure handler, but none would kick into action.

    protected void configure(final HttpSecurity httpSecurity) throws Exception {
        httpSecurity.
        formLogin().
            successHandler(new PropogateQueryStringAuthenticationSuccessHandlerImpl()).
            failureHandler(new SimpleUrlAuthenticationFailureHandlerImpl(new QueryStringPropagateRedirectStrategy())).
        and().
            authorizeRequests().
            antMatchers(managementContextPath + "/**").permitAll().
            anyRequest().authenticated().withObjectPostProcessor(objectPostProcessor).
        and().
            csrf().disable().
            contentTypeOptions().
            xssProtection().
            cacheControl().
            httpStrictTransportSecurity().
        and().
            requestCache().requestCache(new RedisRequestCache(savedRequestRedisTemplate())).
         and().
            sessionManagement().sessionAuthenticationStrategy(sessionAuthenticationStrategy);
    }
    

    I am using spring-security 3.2.4.RELEASE on spring boot 1.1.6.RELEASE(which in turn uses Spring framework 4.0.7.RELEASE)

    Thanks, San

    0 讨论(0)
提交回复
热议问题