Spring Security之匿名使用者
Spring Security為我們提供了一個匿名使用者的功能,我們可以基於此很容易的實現匿名使用者的單獨控制,使我們的站點輕鬆擁有遊客使用者的功能;
如果開啟了匿名使用者的功能,按照Spring Security Filter的執行順序,AnonymousAuthenticationFilter在ExceptionTranslationFilter的前面,在各種認證機制和RememberMeAuthenticationFilter的後面。也就是說,這是最後一步給可能給使用者授權的處理步驟;
下面是Configurer#init和Configurer#configure方法:
@Override
public void init(H http) throws Exception {
if (authenticationProvider == null) {
authenticationProvider = new AnonymousAuthenticationProvider(getKey());
}
if (authenticationFilter == null) {
authenticationFilter = new AnonymousAuthenticationFilter(getKey(), principal,
authorities);
}
authenticationProvider = postProcess(authenticationProvider);
http.authenticationProvider(authenticationProvider);
}
@Override
public void configure(H http) throws Exception {
authenticationFilter.afterPropertiesSet();
http.addFilter(authenticationFilter);
}
可以看到,開啟Anonymous之後,會new一個AnonymousAuthenticationProvider新增到當前的HttpSecurityBuilder配置中,專門用來處理帶有AnonymousAuthenticationToken的請求,new一個AnonymousAuthenticationFilter加到Filter Chain中,用來在合適的條件下往當前請求中填充一個AnonymousAuthenticationToken物件。
從AnonymousAuthenticationFilter可以看出Spring Security對匿名使用者的處理過程;
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
if (SecurityContextHolder.getContext().getAuthentication() == null) {
SecurityContextHolder.getContext().setAuthentication(
createAuthentication((HttpServletRequest) req));
if (logger.isDebugEnabled()) {
logger.debug("Populated SecurityContextHolder with anonymous token: '"
+ SecurityContextHolder.getContext().getAuthentication() + "'");
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("SecurityContextHolder not populated with anonymous token, as it already contained: '"
+ SecurityContextHolder.getContext().getAuthentication() + "'");
}
}
chain.doFilter(req, res);
}
protected Authentication createAuthentication(HttpServletRequest request) {
AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key,
principal, authorities);
auth.setDetails(authenticationDetailsSource.buildDetails(request));
return auth;
}
如果web request到了這個Filter,SecurityContextHolder中還沒有Authentication,建立一個AnonymousAuthenticationToken。AnonymousAuthenticationToken裡面的資訊包括一個key(類似於user表的主鍵),一個principal物件和一個許可權列表authorities,這三個資訊是給Spring Security應用的配置資訊。
在AnonymousAuthenticationFilter裡這麼做的好處是,請求過了這個Filter之後,就可以當作一個正常的帶有Authentication資訊的請求的,後面的認證授權等操作都不用對其做特殊處理。
大家可以根據這個思路,分析下非常類似的RememberMe功能。