shiro源码分析

奋斗吧
奋斗吧
擅长邻域:未填写

标签: shiro源码分析 Html/CSS博客 51CTO博客

2023-06-30 18:24:12 220浏览

shiro源码分析,文章目录简介简介ApacheShiro是一个功能强大且灵活的开源安全框架,可以清晰地处理身份验证,授权,企业会话管理和加密。这是它



文章目录

  • 个人学习路线
  • 简单介绍
  • 怎么进行认证(登录)的
  • SecurityManager详解
  • CachingSecurityManager
  • RealmSecurityManager
  • AuthenticatingSecurityManager
  • AuthorizingSecurityManager
  • SessionsSecurityManager
  • 认证总结
  • 怎么进行鉴权(判断是否有权限)的
  • 授权
  • 总结,以前在使用shiro的回想


个人学习路线

Apache Shiro是一个功能强大且灵活的开源安全框架,可以清晰地处理身份验证,授权,企业会话管理和加密。

这是它的官网:

官网 在官网上面有个快速开始,将源码下载下来,

看看shiro的大体架构:http://shiro.apache.org/architecture.html

我就贴一张最重要的图好了,官网介绍的更加清楚.

shiro源码分析_父类

跑一遍快速开始:

shiro源码分析_父类_02


这时候对shiro有个简单的了解了…

简单介绍

ini配置文件:

# 用户名,密码,角色
[users]
root = secret, admin
guest = guest, guest

presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darklord, schwartz
lonestarr = vespa, goodguy, schwartz

$ 角色 ,对应的权限
[roles]
admin = *
schwartz = lightsaber:*,aa:*
goodguy = winnebago:drive:eagle5,aa:*

简单看看事例代码:

public class Quickstart {
    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);
    public static void main(String[] args) {
        //创建安全中心
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();
        //通过提供的类去简化操作
        SecurityUtils.setSecurityManager(securityManager);

        //获取个用户,抽象的用户.
        Subject currentUser = SecurityUtils.getSubject();

        //获取session
        Session session = currentUser.getSession();
        session.setAttribute("someKey", "aValue");
        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("Retrieved the correct value! [" + value + "]");
        }

        //判断是登录
        if (!currentUser.isAuthenticated()) {
            //用户名密码
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            token.setRememberMe(true);
            try {
                //登录,没有抛出异常就是认证成功,抛出了就是登录失败了.
                currentUser.login(token);
                //各种异常,顾名思义.账户不存在啊,密码错误啊,用户锁住了等等..
            } catch (UnknownAccountException uae) {
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
            }
        }

        //登录成功,获取用户
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

        //是否有指定的角色
        if (currentUser.hasRole("schwartz")) {
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }

        //是否有指定的权限
        if (currentUser.isPermitted("lightsaber:weild")) {
            log.info("You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

      
        //退出
        currentUser.logout();

        System.exit(0);
    }
}

怎么进行认证(登录)的

代码是通过subject调用login方法登录,点到具体实现.
DelegatingSubject这个类实现了Subject,实现了login方法:

Subject currentUser = SecurityUtils.getSubject();
   currentUser.login(token);

SecurityManager详解

我们看默认的实现DefaultSecurityManager类的uml图,

shiro源码分析_父类_03


DefaultSecurityManager继承了SessionsSecurityManager(可以进行session管理)->AuthorizingSecurityManager(可以进行鉴权)->AuthenticatingSecurityManager(可以进行认证)->RealmSecurityManager(可以进行real管理)->CachingSecurityManager(缓存管理了);这不是很明显的装饰者吗?

CachingSecurityManager

这是CachingSecurityManager有CacheManager接口,我们可以实现自己的缓存管理,可以放在redis里,或者mysql,或者整合ehcache等等.然后可以set,get方便扩展.

shiro源码分析_ci_04

RealmSecurityManager

RealmSecurityManager内部维护了一个Realm集合,也提供了各种set,get,方便我们扩展.

shiro源码分析_官网_05

AuthenticatingSecurityManager

内部维护了一个认证器,当然也可以set,get,默认提供了个简单的认证器ModularRealmAuthenticator

shiro源码分析_官网_06

AuthorizingSecurityManager

内部维护了一个鉴权器,也有默认的,set,get等.

shiro源码分析_官网_07

SessionsSecurityManager

内部维护了一个session管理器

shiro源码分析_官网_08

认证总结

通过一系列的继承,那这个默认的DefaultSecurityManager就可以使用认证啊,鉴权啊,缓存啊,session啊,real管理啊等各种功能啦!!!

登录的话,是认证的功能,

首先通过authenticate方法获取个认证信息authenticate这个方法是认证管理器实现的managerAuthenticatingSecurityManager,使用的认证器去进行认证的,this.authenticator是哪个呢?刚刚说了初始化的时候或设置默认的认证器ModularRealmAuthenticator:

shiro源码分析_官网_09


shiro源码分析_官网_10


然后发现实现里面没有authenticate方法,那就说明,在父类里面,子类里没有的方法就去父类里面找,准没错,父类里的抽象方法,那就去子类里面找实现了

然后父类AbstractAuthenticator里面又是调用的doAuthenticate,这个的实现是在ModularRealmAuthenticator认证器里面,然后就是判断是单realm还是多realm分别进行认证.:

shiro源码分析_官网_11


先看多realm认证的话会判断,是不是要全部通过,才算认证成功,或者是只要一个认证通过,

shiro源码分析_ci_12


再看单个realm认证doSingleRealmAuthentication方法:就是通过realm的getAuthenticationInfo(AuthenticationToken token)方法 AuthenticatingRealm这个实现的:

shiro源码分析_父类_13


我们看看doGetAuthenticationInfo的简单实现,一般是我们自己去实现的.:

shiro源码分析_官网_14


shiro源码分析_父类_15


然后就是进行对比了,默认简单的是通过密码进行equals进行对比的…感兴趣可以看看.

当然我们也可以自己实现对比器,CredentialsMatcher这个接口,然后set到我们的管理器里面即可;

对比完成,就是返回认证信息了…

大体流程,我就把网上图贴上来了:

shiro源码分析_父类_16

怎么进行鉴权(判断是否有权限)的

鉴权主要就是两个方法,判断是否有对应的角色,判断是否有对应的权限,对应的方法是hasRole跟isPermitted

这两个方法前面讲过,肯定是通过AuthorizingSecurityManager鉴权管理器进行

就看isPermitted方法好了.

代理subject里面实现了isPermitted方法:hasPrincipals方法判断是否登录.是否进行了认证,如果没有进行认证,那判断是否含有权限就没有意义了;

shiro源码分析_官网_17


然后就是AuthorizingSecurityManager里的实现,通过使用鉴权器进行鉴权,同理,肯定有初始化的鉴权器的,同样是ModularRealmAuthorizer;认证的是ModularRealmAuthenticator名字都是modularRealm开头,哈哈!

shiro源码分析_官网_18


shiro源码分析_ci_19


ModularRealmAuthorizer

shiro源码分析_父类_20


这里的reaml我们就看sampleRealm好了,先看uml图:

shiro源码分析_父类_21


AuthorizingRealm->AuthenticatingRealm->CachingReanm想到了啥,是不是跟跟DefaultSecurityManageer有点相似啊,我就不说了,给个眼神自己体会:

最后就是取出所有权限,然后进行对比,如果有就代表有权限.

shiro源码分析_父类_22

授权

然后在判断是否含有指定权限之前,肯定要给用户赋予用户该有的权限吧,

在AuthorizingRealm的各种鉴权方法里面都会先获取用户的鉴权信息getAuthorizationInfo返回AuthorizationInfo

shiro源码分析_父类_23


shiro源码分析_ci_24

总结,以前在使用shiro的回想

以前做项目的时候总是听别人说,继承AuthorizingRealm然后实现认证,授权两个方法就可以了,shiro就这两个方法,当时也不知道什么原因,只是会用,现在只有通过源码,流程学习,才明白啊!!!

shiro源码分析_官网_25


以前也是写个类实现UserDao,其实就是各种操作操作数据库的接口,就是在鉴权里面获取用户啊,权限.等各种信息用的.

shiro源码分析_官网_26


好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695