1. 程式人生 > >Spring Security之匿名使用者

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功能。