好久不更新blog了,慵懒了!
为了搞清楚 Spring Security 是如何工作了,特地翻了下源代码,查了许多文档,因为我比较在意细节,例如从何时起SS做认证(Authentication),从何时做授权(Authorization),如何定制SS。
Spring Security Filters
Spring Security 框架主要利用 Filter 来实现对 HTTP 请求的认证和授权,掌握了 Filter 就弄明白了SS。
Spring Security 的所有 Filter 都放在 FilterChainProxy 的 List<SecurityFilterChain>
中,Spring-boot 启动时通过 SecurityFilterAutoConfiguration 自动注册 Spring Security’s Filter;
FilterChainProxy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { boolean clearContext = request.getAttribute(FILTER_APPLIED) == null; if (clearContext) { try { request.setAttribute(FILTER_APPLIED, Boolean.TRUE); doFilterInternal(request, response, chain); } finally { SecurityContextHolder.clearContext(); request.removeAttribute(FILTER_APPLIED); } } else { doFilterInternal(request, response, chain); } }
|
可以看出 doFilterInternal(request, response, chain) 就包含了 Spring Security 的认证和授权,认证结果保存着 SecurityContextHolder中,FilterChain 结束后清除。
Authentication
AbstractAuthenticationProcessingFilter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
...
Authentication authResult;
try { authResult = attemptAuthentication(request, response); if (authResult == null) { return; } sessionStrategy.onAuthentication(authResult, request, response); } catch (AuthenticationException failed) { unsuccessfulAuthentication(request, response, failed); return; }
SecurityContextHolder.getContext().setAuthentication(authResult);
rememberMeServices.loginSuccess(request, response, authResult);
if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent( authResult, this.getClass())); }
successHandler.onAuthenticationSuccess(request, response, authResult); }
|
attemptAuthentication(request, response) 需要子类具体实现认证过程,调用 this.getAuthenticationManager().authenticate(Authentication auth) 方法。
AuthenticationManager包含 List<AuthenticationProvider>
, AuthenticationProvider 提供具体的认证过程。
概括一下就是 Filter 调用 AuthenticationManager 进行认证,认证成功后保存 Authentication 到 SecurityContextHolder。
Authorization
FilterSecurityInterceptor 是最后一个 SS Filter,一般情况下用户不需要DIY这部分,因为认证成功后会将 Principle (登录对象) 和 Roles 一同保存在 SecurityContextHolder 中,授权过程就成了根据 request 从 Map<RequestMatcher, Collection> 获取该 uri 所需角色列表,交给 AccessDecisionManager(类似的,它包含 List<AccessDecisionVoter>
, 由 voter 投票) 来决定是否有权限访问,只要有一个 voter 不通过,则无权访问。
code