从代码分析shiro的登陆验证流程

功能:     认证,授权,加密,会话管理,,缓存。。。。

我的理解:什么是shiro,它就是一个基于cookie和session会话技术,采用mvc思想来完成用户的登陆注册和应用资源权限管理的安全框架。它的mvc三层模型分别是jsp/html 【v视图层】    realm【m模型层】  subject+ securityManager【门面+管理=c=(控制层+业务层)】

shiro是一个安全框架。在java ee的mvc三层模型中,每一层它都可以发挥作用
在controller层:shiro创建了一个UsernamePasswordToken对象。用来存储用户的姓名,密码,ip主机地址,Boolean类型的(是否让网站记住我—即是否回传token到客户端的cookie里保存)

subject门面之意,相当于mvc的表现层(接收用户传来的参数,封装成UsernamePasswordToken传给服务层securityManager),服务层是securityManager,它又是一个接口主要由DefaultSecurityManager 实现该接口(里面的业务是:是否授权,是否认证),数据持久层dao是realm,它负责存取用户名,角色,权限。

架构图:

authentication   认证(登录)    authorization  授权(对页面进行操作时shiro会判断你有无相关的操作权限)  session(javaEE和javaSE都可以使用会话)  cryptography  盐加密      concurrency 多线程应用的并发验证

 

运行流程:

web application=============>subject(门面)      ===============>securityManager(核心管家) ========>Realm(数据源,从数据库的用户,角色,权限表中取得数据,相当于dao层)

 

shiro认证(登录)过程:

 

查找接口的实现类:

IDEA 风格 ctrl + alt +B

查看类或接口的继承关系:

ctrl + h

1.获取当前的 Subject. 调用 SecurityUtils.getSubject()
2.测试当前的用户是否已经被认证(登陆).调用 Subject 的 isAuthenticated()
3.若没有被认证,则把用户名和密码封装为 UsernamePasswordToken 对象
    1).创建一个表单页面
    2).把请求提交到 SpringMVC 的 Handler
    3).获取用户名和密码
4.执行登陆: 调用 Subject 的 login(AuthenticationToken) 方法【AuthenticationToken是接口,UsernamePasswordToken是该接口的实现类】
5.自定义 Realm 的方法, 从数据库中获取对应的记录,返回给 Shiro.  【仅仅是认证的话,继承AuthenticatingRealm类即可以了,但如果是授权,还是要实现Realm接口才行】
    1).实际上需要继承org.apache.shiro.realm.AuthenticatingRealm 类
    2).实现doGetAuthenticationInfo(AuthenticationToken) 方法
6.由 shiro 完成密码的对比
    1).通过AuthenticatingRealm 的 credentialsMatcher 属性来进行的密码的比对
    2).把一个字符串加密为MD5,盐值加密
        2.1).在 doGetAuthenticationInfo 方法返回值创建SimpleAuthenticationInfo 对象的时候,需要使用
             SimpleAuthenticationInfo(principal,credentials,credentialsSalt,realmName)构造器
        2.2).使用 ByteSource.Util.bytes()来计算盐值.
        2.3).盐值需要唯一:一般使用随机字符串或user id .
        2.4).使用new SimpleHash(hashAlgorithnName,credentials,salt,hashIterations)来计算盐值加密后的密码的值


授权:
admin用户可访问admin.jsp 和 user.jsp页面, user 用户只能访问 user.jsp页面,密码都为123456
1.授权需要继承AutohorizingRealm 类,并实现其 doGetAuthenticationInfo 方法
2.AuthorizingRealm 类继承自 AuthenticatingRealm 但没有实现AuthenticatingRealm 中的
  doGetAuthenticationInfo 所以认证和授权只需要继承AuthenticatingRealm 就可以了,同时实现它的两个抽象方法


权限注解:
    https://blog.csdn.net/acmman/article/details/78765315
shiro标签使用方法:
    https://blog.csdn.net/yaodieteng1510/article/details/79992247

代码分析:
SecurityUtils.getSubject();得到subject(接口)
org.apache.shiro.subject.support.DelegatingSubject实现了subject接口

subject.login(    UsernamePasswordToken passwordToken  ) 而

UsernamePasswordToken passwordToken是
AuthenticationToken token接口的实现类

 

实际是DelegatingSubject.login()============subject门面之意,相当于mvc的表现层(接收用户传来的参数,封装成UsernamePasswordToken传给服务层securityManager),服务层是securityManager,它又是一个接口主要由DefaultSecurityManager 实现该接口(里面的业务是:是否授权,是否认证),数据持久层dao是realm,它负责存取用户名,角色,权限。

DefaultSecurityManager extends SessionsSecurityManager  #组合SubjectDAO、SubjectFactory主要是创建createSubject、login、logout.

SessionsSecurityManager extends AuthorizingSecurityManager  #实现Session的创建Start和getSession,并清空sessionManager

AuthorizingSecurityManager extends AuthenticatingSecurityManager #组合authorizer权限验证哭器,并清空authorizer

AuthenticatingSecurityManager extends RealmSecurityManager    #组合authenticator身份验证器,并清空authenticator

 RealmSecurityManager extends CachingSecurityManager        #RealmSecurityManager 管理realams,并清空Cachemager

CachingSecurityManager implements SecurityManager, Destroyable, CacheManagerAware, EventBusAware      #CachingSecurityManager 注入Cachemager,并清空Cachemager

 

DefaultSecurityManager通过继承。。。。从而实现securityManager接口。DefaultSecurityManager的login方法

public Subject login(Subject subject, AuthenticationToken token)
AuthenticationInfo info = authenticate(token);    //调用了授权器,而AuthenticationInfo是一个接口,它的实现类是
AbstractAuthenticator,
public abstract class AbstractAuthenticator implements Authenticator, LogoutAware 

关于realm的类:

public class ModularRealmAuthenticator extends AbstractAuthenticator {

             

     protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken){
     
             Collection<Realm> realms = getRealms();
              } 

         protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) {

AuthenticationInfo info = realm.getAuthenticationInfo(token);
   }
    
}

走到下一个Realm的一个实现类:

public abstract class CachingRealm implements Realm{}
public abstract class AuthenticatingRealm extends CachingRealm implements Initializable{

 public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        AuthenticationInfo info = getCachedAuthenticationInfo(token);
        if (info == null) {
            //otherwise not cached, perform the lookup:
            /**注意====================================================>
            *doGetAuthenticationInfo就是我们要继承的org.apache.shiro.realm.AuthenticatingRealm 类,并且要实现的doGetAuthenticationInfo(AuthenticationToken) 方法
            */
            info = doGetAuthenticationInfo(token);
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值