remember-me and authentication-success-handler

匿名 (未验证) 提交于 2019-12-03 00:52:01

问题:

i have strange issue of for login sucess and redirect to page.

below is my spring security configuration.

   @Service public class LoginSucessHandler extends         SavedRequestAwareAuthenticationSuccessHandler {      @Override     public void onAuthenticationSuccess(HttpServletRequest request,             HttpServletResponse response, Authentication authentication)             throws ServletException, IOException {             ...         super.setUseReferer(true);         super.onAuthenticationSuccess(request, response, authentication);     }  } 

now problem of redirect to requested page on success. if i directly refer to any secure url spring redirects me to login page and on successful login to original requested link. but this is not working in case if user had earlier selected remember-me and then closing browser and now requesting direct URL, he is being properly authenticated but instead of redirecting him to requested page spring redirects to /. i have checked log and some spring source code and found it is not able to determine target url.

i have tried to set refer but referer value is null. but one strange thing i have noticed that in spring security configuration if i remove authentication-success-handler from remember-me configuration then it works.

    

not able to figure out issue. is authentication-success-handler implementation requied to be different for form login and remember-me?

回答1:

Remember-me differs from form-login in that authentication occurs during the actual request the user makes. For form-login, the user must first be redirected to the login page, submit the login form and after that they are redirected to the original target (which is usually cached in the session). So form-login requires a redirect, whereas remember-me doesn't. With a remember-me request, the user can be authenticated, and the request allowed to proceed without any intervention.

The primary purpose of an AuthenticationSuccessHandler is to control the navigation flow after authentication, so you wouldn't normally use one with remember-me at all. Using SavedRequestAwareAuthenticationSuccessHandler isn't a good idea, as there won't be a saved request available. If there is no saved request, then by default it will perform a redirect to "/" as you have observed.

If all you want is to add some functionality during a remember-me login, then you can implement the AuthenticationSuccessHandler interface directly without performing a redirect or a forward. As I explained above, you can't use the same implementation for form-login, since the current request is the submission of the login form (usually to the URL j_spring_security_check), and not a request to a URL within your application. So you need a redirect for form-login.



回答2:

You would rather use ApplicationListener and look for the event InteractiveAuthenticationSuccessEvent.

InteractiveAuthenticationSuccessEvent has a property generatedBy which will be the filter, ie UsernamePasswordAuthenticationFilter (form logins) and RememberMeAuthenticationFilter (remeber me logins)

@Component class AuthenticationApplicationListener implements ApplicationListener {    @Override   void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {     //do something   }  } 

using a custom implementation of AuthenticationSuccessHandler on rememberMe will cause problems. Take a look at the flow in RememberMeAuthenticationFilter. if the successHandler is used, the filter chain is bypassed



回答3:

You should implement different authentication-success-handler for login form and for remember-me. If you want to perform redirect in remeber-me handler you can use SimpleUrlAuthenticationSuccessHandler and set DefaultTargetUrl.

public class RememberMeAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {  @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,     Authentication authentication) throws IOException, ServletException {      // ...      super.setAlwaysUseDefaultTargetUrl(true);     super.setDefaultTargetUrl(request.getRequestURL().toString());     super.onAuthenticationSuccess(request, response, authentication); } 


回答4:

Using an AuthenticationSuccessHandler does not work. As stated in another answer, the spring security filter chain will be bypassed!
What works, is to use an ApplicationListener - as another answer also proposes. But to find out, if your user is authenticated by remember me, the idea to use InteractiveAuthenticationSuccessEvent.getGeneratedBy() is not working: getGeneratedBy returns Class, that means a generic. Therefore at runtime you cannot find out, if T is a RememberMeAuthenticationFilter.

What worked fine for me: Use InteractiveAuthenticationSuccessEvent.getAuthentication().

Here an example (by the way: @EventListener is used since Spring Security 4.2 - if you use an earlier version, do the following via implementing ApplicationListener):

@Component public class AuthenticationApplicationListener {      @EventListener     public void handleInteractiveAuthenticationSuccess(InteractiveAuthenticationSuccessEvent event) {         if (RememberMeAuthenticationToken.class.isAssignableFrom(event.getAuthentication().getClass())) {             .... do some stuff     }   }  } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!