前面的章节说完了Subject的创建过程,创建完Subject需要将其保存起来,而保存的过程则由SubjectDAO完成。既然每一次访问都会创建一个新的Subject,那么为什么还需要SubjectDAO来存储呢?其实SubjectDAO做的事情很少,没有存储Subject,只是将当前Subject的authenticated(是否校验成功)和principal(身份)放入到session中。
Subject的生命周期:
- 每一次访问都会创建一个新的subject对象。
- 将创建的subject对象绑定到ThreadContext上,之后通过SecurityUtils便可以在程序的任何地方获取到Subject对象。
- 每一次创建完成subject,都会通过SubjectDAO将subject属性存放到session中去,但是只存放principal(身份)和authenticated(是否校验成功)。
org.apache.shiro.mgt.DefaultSecurityManager中createSubject创建完Subject,调用SubjectDAO保存Subject
public Subject createSubject(SubjectContext subjectContext) {
//create a copy so we don't modify the argument's backing map:
SubjectContext context = copy(subjectContext);
//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;
}
protected void save(Subject subject) {
this.subjectDAO.save(subject);
}
SubjectDAO是一个接口,主要包含save和delete两个方法操作Subject,其主要实现类是DefaultSubjectDAO
public interface SubjectDAO {
/**
* Persists the specified Subject's state for later access. If there is a no existing state persisted, this
* persists it if possible (i.e. a create operation). If there is existing state for the specified {@code Subject},
* this method updates the existing state to reflect the current state (i.e. an update operation).
*
* @param subject the Subject instance for which its state will be created or updated.
* &#