ok.
lets say I have a secure url pattern
/secure/link-profile
optionally, there can be url paramaters appended.
/se
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
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.
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