shiro构建subject流程

本文详细解析了Shiro框架中AbstractShiroFilter的执行流程,重点介绍了如何通过WebSubjectBuilder来创建Subject。在这一过程中,Subject的构建依赖于securityManager,并利用SubjectContext上下文进行代理构建。securityManager则根据上下文信息进一步完成Subject的创建。
摘要由CSDN通过智能技术生成
  1. AbstractShiroFilter 中执行流程
  2.  Throwable t = null;
    
     try {
     // 包装 request 和 response
         final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);
         final ServletResponse response = prepareServletResponse(request, servletResponse, chain);
    
     		// 创建 subject
         final Subject subject = createSubject(request, response);
    
         //noinspection unchecked
         // 由subject执行任务
         subject.execute(new Callable() {
             public Object call() throws Exception {
                 updateSessionLastAccessTime(request, response);
                 executeChain(request, response, chain);
                 return null;
             }
         });
     } catch (ExecutionException ex) {
         t = ex.getCause();
     } catch (Throwable throwable) {
         t = throwable;
     }
    
  3. 实际创建subject 过程, 由WebSubject Builder 来构建
protected WebSubject createSubject(ServletRequest request, ServletResponse response) {
        return new WebSubject.Builder(getSecurityManager(), request, response).buildWebSubject();
    }
  1. 其创建过程上下问,subjectContext
// 父类构造方法,主要创建一个subjectContext, 实际调用了子类的创建了webSubjectContext,
// 在Context上下文中设置securityManager,request, response
public Builder(SecurityManager securityManager) {
            if (securityManager == null) {
                throw new NullPointerException("SecurityManager method argument cannot be null.");
            }
            this.securityManager = securityManager;
            this.subjectContext = newSubjectContextInstance();
            if (this.subjectContext == null) {
                throw new IllegalStateException("Subject instance returned from 'newSubjectContextInstance' " +
                        "cannot be null.");
            }
            this.subjectContext.setSecurityManager(securityManager);
        }
public Builder(SecurityManager securityManager, ServletRequest request, ServletResponse response) {
            super(securityManager);
            if (request == null) {
                throw new IllegalArgumentException("ServletRequest argument cannot be null.");
            }
            if (response == null) {
                throw new IllegalArgumentException("ServletResponse argument cannot be null.");
            }
            // 在context 上下文中设置请求和回应
            setRequest(request);
            setResponse(response);
        }
  1. 构建由securityManager 代理构建
// 有父build 创建
  public WebSubject buildWebSubject() {
            Subject subject = super.buildSubject();
            if (!(subject instanceof WebSubject)) {
                String msg = "Subject implementation returned from the SecurityManager was not a " +
                        WebSubject.class.getName() + " implementation.  Please ensure a Web-enabled SecurityManager " +
                        "has been configured and made available to this builder.";
                throw new IllegalStateException(msg);
            }
            return (WebSubject) subject;
        }
        // 父类转交给securityManager 通过上下文创建
 public Subject buildSubject() {
            return this.securityManager.createSubject(this.subjectContext);
        }

securityManager 通过上下文创建

    public Subject createSubject(SubjectContext subjectContext) {
    // 重新复制一份上下文,不修改原来参数中的上下文,有subjectContext /webSubjectContext
        //create a copy so we don't modify the argument's backing map:
        SubjectContext context = copy(subjectContext);
		// 确保上下文中有securityManager,如果没有则新增加一个
        //ensure that the context has a SecurityManager instance, and if not, add one:
        context = ensureSecurityManager(context);

        //Resolve an associated Session (usually based on a referenced session ID), and place it in the context before
        //sending to the SubjectFactory.  The SubjectFactory should not need to know how to acquire sessions as the
        //process is often environment specific - better to shield the SF from these details:
        context = resolveSession(context);

        //Similarly, the SubjectFactory should not require any concept of RememberMe - translate that here first
        //if possible before handing off to the SubjectFactory:
        context = resolvePrincipals(context);

        Subject subject = doCreateSubject(context);

        //save this subject for future reference if necessary:
        //(this is needed here in case rememberMe principals were resolved and they need to be stored in the
        //session, so we don't constantly rehydrate the rememberMe PrincipalCollection on every operation).
        //Added in 1.2:
        save(subject);

        return subject;
    }
// 解析sesssion , 先从 上下文中获取,如果没有则从sessionManager 中查询
@SuppressWarnings({"unchecked"})
    protected SubjectContext resolveSession(SubjectContext context) {
    // 先从 上下文中获取
        if (context.resolveSession() != null) {
            log.debug("Context already contains a session.  Returning.");
            return context;
        }
        try {
            //Context couldn't resolve it directly, let's see if we can since we have direct access to 
            //the session manager:
            Session session = resolveContextSession(context);
            // 如果sessionManager 中有则设置到上下文中
            if (session != null) {
                context.setSession(session);
            }
        } catch (InvalidSessionException e) {
            log.debug("Resolved SubjectContext context session is invalid.  Ignoring and creating an anonymous " +
                    "(session-less) Subject instance.", e);
        }
        return context;
    }
    // 从sessionManager 中获取session
  protected Session resolveContextSession(SubjectContext context) throws InvalidSessionException {
  // 从上下文中中获取sessionKey
        SessionKey key = getSessionKey(context);
        if (key != null) {
        // 从sessionManager 中和去session
            return getSession(key);
        }
        return null;
    }
    // 如果是webSubjectContext则新建webSessionKey, 交由web
       protected SessionKey getSessionKey(SubjectContext context) {
        if (WebUtils.isWeb(context)) {
            Serializable sessionId = context.getSessionId();
            ServletRequest request = WebUtils.getRequest(context);
            ServletResponse response = WebUtils.getResponse(context);
            return new WebSessionKey(sessionId, request, response);
        } else {
        // 直接冲上下文中获取sessionKey
            return super.getSessionKey(context);

        }
    }
// 通过sessionKey 获取session, 交由sessionManager 获取session
public Session getSession(SessionKey key) throws SessionException {
        return this.sessionManager.getSession(key);
    }
    // ServletContainerSessionManager 的实现 直接代理httpSession
    public Session getSession(SessionKey key) throws SessionException {
        if (!WebUtils.isHttp(key)) {
            String msg = "SessionKey must be an HTTP compatible implementation.";
            throw new IllegalArgumentException(msg);
        }

        HttpServletRequest request = WebUtils.getHttpRequest(key);

        Session session = null;

        HttpSession httpSession = request.getSession(false);
        if (httpSession != null) {
            session = createSession(httpSession, request.getRemoteHost());
        }

        return session;
    }
// 解析
protected SubjectContext resolvePrincipals(SubjectContext context) {
// 容器解析 principal 如果没有则成记住我中获取
        PrincipalCollection principals = context.resolvePrincipals();

        if (isEmpty(principals)) {
            log.trace("No identity (PrincipalCollection) found in the context.  Looking for a remembered identity.");

            principals = getRememberedIdentity(context);

            if (!isEmpty(principals)) {
                log.debug("Found remembered PrincipalCollection.  Adding to the context to be used " +
                        "for subject construction by the SubjectFactory.");

                context.setPrincipals(principals);


            } else {
                log.trace("No remembered identity found.  Returning original context.");
            }
        }

        return context;
    }
   // 上下文中解析pricipal, 先上下文中是否直接存储,
       public PrincipalCollection resolvePrincipals() {
       // 上下文中直接存储
        PrincipalCollection principals = getPrincipals();

        if (isEmpty(principals)) {
        // 上下文中认证信息中存储的
            //check to see if they were just authenticated:
            AuthenticationInfo info = getAuthenticationInfo();
            if (info != null) {
                principals = info.getPrincipals();
            }
        }
		// 已有subject中的中的
        if (isEmpty(principals)) {
            Subject subject = getSubject();
            if (subject != null) {
                principals = subject.getPrincipals();
            }
        }
		// session中的
        if (isEmpty(principals)) {
            //try the session:
            Session session = resolveSession();
            if (session != null) {
                principals = (PrincipalCollection) session.getAttribute(PRINCIPALS_SESSION_KEY);
            }
        }

        return principals;
    }

// 交由subjectFactoury 来创建,实际就是上下问中的属性,如果没有可能从session 中找
protected Subject doCreateSubject(SubjectContext context) {
        return getSubjectFactory().createSubject(context);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值