spring boot(2.3.10)安全框架记住我会导致非安全页面出错

cu6pst1q  于 2021-09-29  发布在  Java
关注(0)|答案(1)|浏览(231)

我正在使用持久的记忆我功能。它大部分时间都在工作,但偶尔也会引发cookietheftexception。甚至对于匿名页面(用户不必登录)。为了解决这个问题。。。我创建了@exceptionhandler方法,如下所示,将用户重定向到同一页面并删除会话。但是getrequesturl()给出了/error url,而不是来自浏览器的url。我想我错过了一个获取原始url的方法,或者可能有其他更好的方法来处理它。

  1. @ControllerAdvice
  2. public class CookieTheftExceptionHandler implements ErrorViewResolver {
  3. @Override
  4. @ExceptionHandler(RememberMeAuthenticationException.class)
  5. public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
  6. log.warn("RememberMe authentication occurred for url={}, redirecting the user to login page, error: {}", request.getRequestURL());
  7. String redirectURL = request.getRequestURL();
  8. redirectURL = redirectURL == null ? Attributes.LOGIN_URL : redirectURL;
  9. if (redirectURL.contains("/error"))
  10. redirectURL = Attributes.LOGIN_URL;
  11. clearSession(request);
  12. log.info("Redirecting the user to URL: {}", redirectURL);
  13. return new ModelAndView(Views.REDIRECT + redirectURL);
  14. }
  15. private void clearSession(HttpServletRequest request) {
  16. try {
  17. HttpSession session = request.getSession(false);
  18. if (session != null) {
  19. session.invalidate();
  20. }
  21. SecurityContext context = SecurityContextHolder.getContext();
  22. context.setAuthentication(null);
  23. SecurityContextHolder.clearContext();
  24. } catch (Exception ex) {
  25. log.warn("Not able to clear user's session", ex);
  26. }
  27. }
  28. }

知道为什么request.getrequesturl()将结果调用到/error输出中吗。如果这不是正确的方法,如何处理好它。我想要的是,当用户在非安全页面上时,如果“记住我”中存在问题……只需清除该用户并将其视为匿名用户即可。

uqzxnwby

uqzxnwby1#

我找到了一个解决方案,但不确定这是否是解决这个问题的“正确方法”。把它放在这里,以防有人发现它有用。
背景:spring security使用PersistentTokenBasedMemberMeservices类来处理基于持久令牌的验证。我创建了自己的自定义TokenBasedMemberMeservices类,将PersistentTokenBasedMemberMeservices中的所有代码复制到该类中。除了类名之外,代码完全相同。在ProcessAutologyCookie(..)方法中,我修改了抛出cookietheftexception的代码。相反,我抛出了rememberAuthenticationException。这解决了我的问题,不需要编写exceptionhandler。代码如下:

  1. My SecurityConfig class:
  2. ..
  3. ..
  4. .and()
  5. .csrf().disable()
  6. .exceptionHandling().accessDeniedPage("/user/403/")
  7. .and()
  8. .rememberMe()
  9. .rememberMeParameter("remember-me")
  10. .rememberMeServices(tokenBasedRememberMeServices);
  11. tokenBasedRememberMeServices is autowired to this class.

TokenBasedMemberMeservices(仅更改代码):

  1. @Service("tokenBasedRememberMeServices")
  2. public class TokenBasedRememberMeServices extends AbstractRememberMeServices {
  3. @Autowired(required = true)
  4. public TokenBasedRememberMeServices(@Value("${app.security.remember-me.key}") String key,
  5. @Qualifier("userInfoService") UserDetailsService userDetailsService,
  6. @Qualifier("rememberMePersistentTokenRepository") PersistentTokenRepository tokenRepository) {
  7. super(key, userDetailsService);
  8. random = new SecureRandom();
  9. this.tokenRepository = tokenRepository;
  10. }
  11. protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) {
  12. ...
  13. ..
  14. // We have a match for this user/series combination
  15. if (!presentedToken.equals(token.getTokenValue())) {
  16. // Token doesn't match series value. Delete all logins for this user
  17. // and throw
  18. // an exception to warn them.
  19. tokenRepository.removeUserTokens(token.getUsername());
  20. String errorMessage = messages.getMessage("PersistentTokenBasedRememberMeServices.cookieStolen",
  21. "Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack.");
  22. log.warn("request token doesn't match with the one stored in database, {}", errorMessage);
  23. throw new RememberMeAuthenticationException(errorMessage);
  24. }
  25. ....
  26. ....
  27. }
展开查看全部

相关问题