简体   繁体   中英

Spring Security - Retaining URL parameters on redirect to login

ok.

lets say I have a secure url pattern

/secure/link-profile

optionally, there can be url paramaters appended.

/secure/link-profile?firstName=Bob&secondName=Smith&membershipNumber=1234

how can I make it so that those url params are carried over to the login page?

/login?firstName=Bob&secondName=Smith&membershipNumber=1234

the basic premise is that we offer rewards integration with a 3rd party, who will send their users to us. They will be taken to a page to link their 3rd party account/profile with their/our website user. If however, they dont have an existing account with us, then on the login page, they will go to the signup page, and we would then like to prepopulate some of their details that the 3rd party has passed on to us.

thanks in advance

spring security 2.0.7.RELEASE spring framework 3.1.1.RELEASE

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.

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

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM