Shiro 框架 createSubject 的过程分析

调用顺序


>> AbstractShiroFilter.doFilterInternal(ServletRequest, ServletResponse, FilterChain) 

>> AbstractShiroFilter.createSubject(ServletRequest, ServletResponse)

>> WebSubject.Builder.buildWebSubject()

>> Subject.Builder.buildSubject()

>> SecurityManager.createSubject(SubjectContext)

 

具体流程


AbstractShiroFilter.doFilterInternal() 方法中调用了 createSubject(),观察这个方法。

protected WebSubject createSubject(ServletRequest request, ServletResponse response) {
	return new WebSubject.Builder(getSecurityManager(), request, response).buildWebSubject();
}

该方法使用了 WebSubject,可以推测,它需要创建一个 Web 类型的 Subject。

PS:使用 Builder 设计模式。

下面观察 WebSubject.Builder.buildWebSubject() 源码:

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;
}

上面方法调用了 super.buildSubject(),继续观察 super.buildSubject():

public Subject buildSubject() {
	return this.securityManager.createSubject(this.subjectContext);
}

至此,我们发现,原来是 secuirtyManager 创建了 Subject。

其实在 Shiro-Spring Web 框架中,securityManager 的实现类只可能是 DefaultWebSecurityManager(因为只有这个实现类是 WebSecurityManager 接口的实现类),那我们下面就只看它的 createSubject() 方法:

public Subject createSubject(SubjectContext subjectContext) {
	SubjectContext context = copy(subjectContext);

	context = ensureSecurityManager(context);

	context = resolveSession(context);

	context = resolvePrincipals(context);

	Subject subject = doCreateSubject(context);

	save(subject);

	return subject;
}

见明知意,应该知道,doCreateSubject() 就是创建 Subject 的真正方法:

protected Subject doCreateSubject(SubjectContext context) {
    return getSubjectFactory().createSubject(context);
}

方法获取了 SubjectFactory(工厂设计),然后调用了工厂的 createSubject() 方法:

public Subject createSubject(SubjectContext context) {
	if (!(context instanceof WebSubjectContext)) {
		return super.createSubject(context);
	}
	WebSubjectContext wsc = (WebSubjectContext) context;
	SecurityManager securityManager = wsc.resolveSecurityManager();
	Session session = wsc.resolveSession();
	boolean sessionEnabled = wsc.isSessionCreationEnabled();
	PrincipalCollection principals = wsc.resolvePrincipals();
	boolean authenticated = wsc.resolveAuthenticated();
	String host = wsc.resolveHost();
	ServletRequest request = wsc.resolveServletRequest();
	ServletResponse response = wsc.resolveServletResponse();

	return new WebDelegatingSubject(principals, authenticated, host, session, sessionEnabled, request, response,
			securityManager);
}

上面的方法主要是以 context 出发,从而获得各种各样的参数,进而传递给 WebDelegatingSubject 构造器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罐装面包

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值