Shiro相关过滤器
ShiroConfig
1 | public class ShiroConfig { |
登录流程
1.login
1 | ("/login") |
- 通过SecurityUtils.getSubject获取当前主体
- 然后将用户名和密码分装为UsernamePasswordToken
- 调用login方法
2.DefaultSecurityManager
1 | public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException { |
- 调用authenticate(token)
3.AbstractAuthenticator
1 | public final AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException { |
4.ModularRealmAuthenticator
1 | protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException { |
5.AuthenticatingRealm
1 | public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { |
- 先从内存中获取
- 如果内存中为null,就执行自定义的realm中的doGetAuthenticationInfo方法进行认证。
6.AdminAuthorizingRealm(自定义Realm)
1 | public class AdminAuthorizingRealm extends AuthorizingRealm { |
- 这里会从数据库中根据username查询出对象,并生成一个SimpleAuthenticationInfo返回。用于和用户提交的username和password做比对。(为什么这里不直接判断一下密码是否正确呢?)
7.返回了SimpleAuthenticationInfo之后,继续返回到AuthenticatingRealm,进行用户信息校验。
1 | protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException { |
8.SimpleCredentialsMatcher
1 | public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { |
- 先获取用户提交的password
- 再获取从数据库中查询出来的password
- 进行校验
9.校验成功之后,回到最初的DefaultSecurityManager
1 | Subject loggedIn = createSubject(token, info, subject); |
- 这里会创建一个Subject(主体)
authc认证
1 | filterChainDefinitionMap.put("/admin/test1", "authc"); |
1.AccessControlFilter
1 | public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { |
2.AuthenticatingFilter
1 | protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { |
3.AuthenticationFilter
1 | protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { |
- 首先通过isAccessAllowed方法判断是否已经授权
- 如果没有授权,就调用FormAuthenticationFilter中的onAccessDenied方法。
- 如果是login请求:就执行登录
- 如果不是,就重定向到之前设定的loginUrl
4.FormAuthenticationFilter
1 | protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { |
授权过程
1 | filterChainDefinitionMap.put("/admin/test2", "roles[admin]"); |
1.AccessControlFilter
1 | public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { |
2.RolesAuthorizationFilter
1 | public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException { |
- 获取需要的角色
3.DelegatingSubject
1 | public boolean hasAllRoles(Collection<String> roleIdentifiers) { |
4.AuthorzingSecurityManager
1 | public boolean hasAllRoles(PrincipalCollection principals, Collection<String> roleIdentifiers) { |
4.ModularRealmAuthorizer
1 | public boolean hasAllRoles(PrincipalCollection principals, Collection<String> roleIdentifiers) { |
- 这里会遍历realms
5.AuthorizingRealm
1 | public boolean hasRole(PrincipalCollection principal, String roleIdentifier) { |
和之前的认证一样,也会先从内存中寻找,没有的话就从自定义的realm中调用doGetAuthorizationInfo获取授权信息。
6.AdminAuthorizingRealm
1 | public class AdminAuthorizingRealm extends AuthorizingRealm { |
- 主要是RolesAuthorizationFilter中的isAccessAllowed方法、
加密(加盐)
1 |
|
1 |
|
- 在自定义realm的父类AuthenticatingRealm中,有个CredentialsMatcher credentialsMatcher属性,这就是指定加密算法的属性,默认为SimpleCredentialsMatcher。
- 在生成SimpleAuthenticatinInfo对象时,将salt传入。
- HashedCredentialsMatcher中的hashProvidedCredentials方法中会使用该salt为用户提交的密码进行加密(和数据库中查询出来的已加密的密码比较)
HashedCredentialsMatcher1
2
3
4
5public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
Object tokenHashedCredentials = hashProvidedCredentials(token, info);
Object accountCredentials = getCredentials(info);
return equals(tokenHashedCredentials, accountCredentials);
}
1 | protected Object hashProvidedCredentials(AuthenticationToken token, AuthenticationInfo info) { |
1 | protected Object getCredentials(AuthenticationInfo info) { |