Spring Security3学习-SecurityContext持久化

Spring Security3默认过滤器链的第一个过滤器就是org.springframework.security.web.context.SecurityContextPersistenceFilter,这个Filter就是持久化SecurityContext实例的,流程图:
Spring Security3学习-SecurityContext持久化_第1张图片
 看SecurityContextPersistenceFilter代码:

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        if (request.getAttribute(FILTER_APPLIED) != null) {
            // ensure that filter is only applied once per request
            chain.doFilter(request, response);
            return;
        }

        final boolean debug = logger.isDebugEnabled();

        request.setAttribute(FILTER_APPLIED, Boolean.TRUE);

        if (forceEagerSessionCreation) {
            HttpSession session = request.getSession();

            if (debug && session.isNew()) {
                logger.debug("Eagerly created session: " + session.getId());
            }
        }

        HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
        // 从SecurityContextRepository中获取SecurityContext实例
        SecurityContext contextBeforeChainExecution = repo.loadContext(holder);

        try {
           // 将SecurityContext实例到SecurityContextHolder中,后面的过滤器以及我们在程序中一般都从这个holder中拿SecurityContext实例
            SecurityContextHolder.setContext(contextBeforeChainExecution);

            chain.doFilter(holder.getRequest(), holder.getResponse());

        } finally {
            // 先获取SecurityContext实例
            SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();
            // Crucial removal of SecurityContextHolder contents - do this before anything else.
            //再从holder中清除
            SecurityContextHolder.clearContext();
            // 当SecurityContext实例被update,或session中SecurityContext实例为空,将其放入session中
            repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());
            request.removeAttribute(FILTER_APPLIED);
            if (debug) {
               logger.debug("SecurityContextHolder now cleared, as request processing completed");
             }
        }
}

 分析一下HttpSessionSecurityContextRepository的loadContext方法:

    public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
        HttpServletRequest request = requestResponseHolder.getRequest();
        HttpServletResponse response = requestResponseHolder.getResponse();
        HttpSession httpSession = request.getSession(false);
        // 从session中获取SecurityContext对象
        SecurityContext context = readSecurityContextFromSession(httpSession);

        if (context == null) {
            if (logger.isDebugEnabled()) {
                logger.debug("No SecurityContext was available from the HttpSession: " + httpSession +". " +
                        "A new one will be created.");
            }
            // 如果SecurityContext对象是空的,创建一个SecurityContext实例
            context = generateNewContext();

        }
        // 注意:此处用SaveToSessionResponseWrapper替换了原生的httpresponse对象,可能和自定义的response wrapper对象有冲突。
        requestResponseHolder.setResponse(new SaveToSessionResponseWrapper(response, request,
                httpSession != null, context.hashCode()));

        return context;
    }

 这个过滤器比较简单,它维护了SecurityContextHolder中SecurityContext实例,我们也很方便的从SecurityContextHolder中获取SecurityContext对象

你可能感兴趣的:(Spring,Security3)