shiro login源码

登录的代码示例为:
Subjectsubject=SecurityUtils.getSubject();
UsernamePasswordTokenusernamePasswordToken=newUsernamePasswordToken(
username,
password
);
usernamePasswordToken.setRememberMe(rememberMe);
try{
//进行验证,这里可以捕获异常,然后返回对应信息
subject.login(usernamePasswordToken);
//subject.checkRole("admin");
//subject.checkPermissions("query","add");
}catch(AuthenticationExceptione){
System.out.println(e.toString());
return"error";
}catch(AuthorizationExceptione){
System.out.println(e.toString());
return"error";
}
return"index";


步骤一:
SecurityUtils.getSubject(); ---> ThreadContext.getSubject(); -----> 从ThreadContext.getValue(key)中获取出Map<Object,Object>,其中包含两个值:

shiro login源码

并取出key值为 org.apache.shiro.util.ThreadContext_SUBJECT_KEY 的 WebDelegatingSubject对象

(其中包含 request,response,principals,authenticated,host,session,securityManager(即另一个key)等)

shiro login源码

其中的session对象属性如下:

shiro login源码

步骤二:
利用登录的username和password构造 UsernamePasswordToken 对象,此对象包含如下属性:

 shiro login源码

步骤三:
执行subject.login(usernamePasswordToken); 会执行WebDelegatingSubject的login方法:
①执行clearRunAsIdentitiesInternal,将session中的attribute移除: org.apache.shiro.subject.support.DelegatingSubject.RUN_AS_PRINCIPALS_SESSION_KEY
②执行securityManager(DefaultWebSecurityManager)的login方法:
  1.执行authenticate;
    AbstractAuthenticator的authenticate
      1.执行实现类ModularRealmAuthenticator的doAuthenticate方法);
        1.获取所有的realm,判断是一个realm还是多个
        2.然后执行doSingleRealmAuthentication或doMultiRealmAuthentication;
      1.执行doSingleRealmAuthentication的话会执行AuthenticatingRealm的getAuthenticationInfo方法
1.先从cache中获取AuthenticationInfo;
2.如果为空,再调用用户实现的realm的doGetAuthenticationInfo方法;
3.成功后进行缓存;
2.将执行结果通知所有的AuthenticationListener(可自行实现);
2.执行createSubject;
1.先创建SubjectContext对象,并赋值:Authenticated、info、token、securityManager、subject等信息;
2.将SubjectContext对象中的信息包装成为DelegatingSubject对象,即最终创建的Subject对象;
2.通过反射获取principals为PrincipalCollection对象,并set到session的Attribute中,key为org.apache.shiro.subject.support.DefaultSubjectContext_PRINCIPALS_SESSION_KEY;
3.设置为AuthenticationState为true,并set到session的Attribute中,key为org.apache.shiro.subject.support.DefaultSubjectContext_AUTHENTICATED_SESSION_KEY;


3.通知RememberMeManager结果,执行rememberMeSuccessfulLogin方法:
1.获取RememberMeManager对象,并执行其onSuccessfulLogin方法(执行其实现类AbstractRememberMeManager的onSuccessfulLogin方法)
1.执行forgetIdentity方法,(执行实现类CookieRememberMeManager的forgetIdentity方法)
1.获取cookie(org.apache.shiro.web.servlet.Cookie)对象,并执行removeFrom方法,执行其实现类SimpleCookie的removeFrom方法
2.如果是记住我,则执行rememberIdentity方法(执行其实现类CookieRememberMeManager的rememberSerializedIdentity方法)
1.获取cookie(org.apache.shiro.web.servlet.Cookie)对象,将Base64.encodeToString(byte[] serialized)的cookie值写入,执行其实现类SimpleCookie的saveTo方法:

③将session包装为StoppingAwareProxiedSession类型,重写其stop方法: