Spring Security 框架在用户成功登录后的处理逻辑,相对来说比较复杂,比较绕,下面我们就关键逻辑,进行相关分析。
首先,框架默认的 AuthenticationSuccessHandler 为 SavedRequestAwareAuthenticationSuccessHandler。
判断当前Request是否缓存(另外需要看 Spring Security 是否开启了 Request 缓存,默认是开启的)。
...... SavedRequest savedRequest = requestCache.getRequest(request, response);if (savedRequest == null) { super.onAuthenticationSuccess(request, response, authentication); return;}......
如果 Spring Security 关闭了 Request 缓存,或者当前 Request 并没有被缓存,那么就走默认的认证成功逻辑。
否则,继续根据 alwaysUseDefaultTargetUrl 判断是否永远重定向到 defaultTargetUrl;亦或是,如果配置了targetUrlParameter 且当前 request 存在该参数值,那么,从缓存中移除当前request,并走默认的认证成功逻辑。
...... String targetUrlParameter = getTargetUrlParameter();if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) { requestCache.removeRequest(request, response); super.onAuthenticationSuccess(request, response, authentication); return;} ......
以上情况都不满足,即 Spring Security 开启了 Request 缓存,且当前 request 被缓存了,框架即重定向到缓存 request 对应的地址。
// Use the DefaultSavedRequest URLString targetUrl = savedRequest.getRedirectUrl();logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);getRedirectStrategy().sendRedirect(request, response, targetUrl);
默认的认证成功逻辑,也不复杂,就是判断要重定向的地址这个逻辑,比较繁琐。
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) { if (isAlwaysUseDefaultTargetUrl()) { return defaultTargetUrl; } // Check for the parameter and use that if available String targetUrl = null; if (targetUrlParameter != null) { targetUrl = request.getParameter(targetUrlParameter); if (StringUtils.hasText(targetUrl)) { logger.debug("Found targetUrlParameter in request: " + targetUrl); return targetUrl; } } if (useReferer && !StringUtils.hasLength(targetUrl)) { targetUrl = request.getHeader("Referer"); logger.debug("Using Referer header: " + targetUrl); } if (!StringUtils.hasText(targetUrl)) { targetUrl = defaultTargetUrl; logger.debug("Using default Url: " + targetUrl); } return targetUrl;}
简而言之,就是如果 alwaysUseDefaultTargetUrl 为true,则重定向 defaultTargetUrl;如果配置了 targetUrlParameter 且其对应的值不为空,则重定向到该地址;如果配置的 useReferer 为 true 且其值不为空,则重定向到该地址;否则,则重定向到 defaultTargetUrl。
另外,针对成功登录后的这段复杂逻辑,画了一个流程图,可以参照这些关键代码,加深一下理解。