Shiro总结和常见面试题

Shiro总结和常见面试题Shiro 总结和常见面试题一 什么是 shiroShiro 是一个强大易用的 java 安全框架 提供了认证 授权 加密 会话管理 与 web 集成 缓存等功能 对于任何一个应用程序 都可以提供全面的安全服务 相比其他安全框架 shiro 要简单的多 二 Shiro 的核心概念 Subject SecurityMana RealmSubject 主体 代表了当前 用户 这个用户不一定是一个具体的

Shiro总结和常见面试题

一、 什么是shiro

Shiro是一个强大易用的java安全框架,提供了认证、授权、加密、会话管理、与web集成、缓存等功能,对于任何一个应用程序,都可以提供全面的安全服务,相比其他安全框架,shiro要简单的多。

二、 Shiro的核心概念Subject、SecurityManager、Realm

三、 Authentication 身份验证

  1. 首先调用Subject.login(token)进行登录,其会自动委托给SecurityManager,调用之前必须通过SecurityUtils.setSecurityManager()设置;
  2. SecurityManager负责真正的身份验证逻辑;它会委托给Authenticator进行身份验证;
  3. Authenticator才是真正的身份验证者,shiro api中核心的身份认证入口点,此处可以自定义插入自己的实现;
  4. Authenticator可能会委托给相应的AuthenticationStrategy进行多Realm身份验证,默认ModularRealmAuthenticator会调用AuthenticationStrategy进行多Realm身份验证;
  5. Authenticator会把相应的token传入Realm,从Realm获取身份验证信息,如果没有返回/抛出异常表示身份验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问。
    Authenticator及AuthenticationStrategy
  6. Authenticator的职责是验证用户账号,是shiro api中身份验证核心的入口点。
  7. AuthenticationStrategy 认证策略 ModularRealmAuthenticator默认使用AtLeastOneSuccessfulStrategy策略
    1> FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略;
    2> AtLeastOneSuccessfulStrategy:只要有一个Realm验证成功即可,和FirstSuccessfulStrategy不同,返回所有Realm身份验证成功的认证信息;
    3> AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。


自定义实现认证时一般继承AbstractAuthenticationStrategy即可

四、 Authorization 授权

  1. 编程式:通过写if/else授权代码完成
    Subject subject = SecurityUtils.getSubject();
    If(subject.hasRole(“admin”){

    // 有权限
    }else{

    // 无权限
    }





  2. 注解
    @RequiresRoles(“admin”)
    public void helloWord(){

    // 有权限
    }



  3. Jsp/gsp标签







    基于资源的访问控制
    1. 隐式角色:硬编码的方式(if/else);粗粒度造成的问题:如果有一天不需要了那么就需要修改相应代码把所有相关的地方进行删除;


  4. 显示角色:规则:资源标识符:操作(user:create,user:update)这种方式叫资源级别的粒度;好处:如果需要修改都是一个资源级别的修改,不会对其他模块代码产生影响,粒度小;但实现起来可能稍微复杂点,需要维护“用户—角色,角色—权限(资源:操作)”之间的关系
    Permission
    字符串通配符权限
    规则:资源标识符 : 操作 : 对象实例ID
    “:”表示资源/操作/实例的分割
    “,”表示操作的分割
    “*”表示任意资源/操作/实例





  5. 单个资源多个权限
    Role=system:user:update,system:user:delete
    等价于role=system:user:update,delete,但是反过来是规则不成立
    代码判断
    subject().checkPermissions(“system:user:update,delete”)



  6. 单个资源全部权限:role=sys:user:*/sys:user
  7. 所有资源全部权限:role=*:view;subject.checkPermissions(“user:view”);
  8. 实例级别的权限
    单实多限:role=”user:update,delete:1”;
    subject().checkPermissions(”user:update,delete:1”);
    all实单限:role=”user:auth:”;
    subject().checkPermissions(“user:auth:1”, “user:auth:2”);
    all实all限:role=”user:

    ?”;
    subject().checkPermissions(“user:view:1”, “user:auth:2”);



授权流程:

  1. 首先调用Subject.isPermitted*/hasRole*接口,其会委托给SecurityManager,而SecurityManager接着会委托给Authorizer;
  2. Authorizer是真正的授权者,如果我们调用如isPermitted(“user:view”), 其首先会通过PermissionResolver把字符串转换成相应的Permission实例;
  3. 在进行授权之前,其会调用相应的Realm获取Subject相应的角色/权限用于匹配传入的角色/权限;
  4. Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托给ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted*/hasRole*会返回true, 否则返回false表示授权失败。

五、 Cryptography 加密

  1. 首先创建一个DfaultHashService,默认使用SHA-512算法;
  2. 可以通过hashAlgorithmName属性修改算法;
  3. 可以通过privateSalt设置一个私盐,其在散列时自动与用户传入的公盐混合产生一个新盐;
  4. 可以通过generatePublicSalt属性在用户没有传入公盐的情况下是否生成公盐;
  5. 可以设置randomNumberGenerator用于生成公盐;
  6. 可以设置hashIterations属性来修改默认加密迭代次数;
  7. 需要构建一个HashRequest,传入算法、数据、公盐、迭代次数。
    生成随机数
    SecureRandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
    randomNumberGenerator.setSeed(“159”.getBytes());
    String hex = randomNumberGenerator.nextBytes().toHex();
    加密/解密
    提供对称式加密/解密算法的支持,如AES、Blowfish等
    PasswordService/CredentialsMatcher
    用于提供加密密码及验证密码服务
    Shiro默认提供了PasswordService实现DefaultPasswordService;CredentialsMatcher实现PasswordMatcher及HashedCredentialsMatcher(更强大)
    HashedCredentialsMatcher实现密码验证服务
    Shiro提供了CredentialsMatcher的散列实现HashedCredentialsMatcher,和PasswordMatcher不同的是,它只是用于密码验证,且可以提供自己的盐,而不是随机生成盐,且生成密码散列值的算法需要自己写,因为能提供自己的盐










六、 Realm 域

定义Realm(自定义Realm继承AuthorizingRealm即可)

  1. UserRealm父类AuthorizingRealm将获取Subject相关信息分成两步:获取身份验证信息(doGetAuthenticationInfo)及授权信息(doGetAuthorizationInfo)
  2. doGetAuthenticationInfo获取身份验证相关信息:首先根据传入的用户名获取User信息;如果user为空,那么抛出没找到账号异常UnknownAccountExecption;如果user找到但却被锁定了抛出锁定异常LockedAccountException;最后生成AuthenticationInfo信息,交给间接父类AuthenticatingRealm使用CredentialsMatcher进行判断密码是否匹配,如果不匹配将抛出密码错误异常信息IncorrectCredentialsException;如果密码重试次数太多将抛出超出重试次数异常ExcessiveAttemptsException;在组装SimpleAuthenticationInfo信息时,需要传入:身份信息(用户名)、凭据(密文密码)、盐(username+salt),CredentialsMatcher使用盐加密传入的明文密码和此处的密文密码进行匹配。
  3. doGetAuthorizationInfo获取授权信息:PrincipalCollection是一个身份集合,因为只用到了一个Realm,所以直接调用getPrimaryPrincipal得到之前传入的用户名即可;然后根据用户名调用UserService接口获取角色及权限信息。

AuthenticationInfo的两个作用

  1. 如果Realm是AuthenticatingRealm子类,则提供给AuthenticatingRealm内部使用的CredentialsMatcher进行凭据验证;(如果没有继承它需要在自己的Realm中实现验证);
  2. 提供给SecurityManager来创建Subject(提供身份信息);

七、 拦截器

  1. 首先判断是否已经登录过了,如果已经登录过了继续拦截器链即可;
  2. 如果没有登录,看看是否是登录请求,如果是get方法的登录页面请求,则继续拦截器链(到请求页面),否则如果是get方法的其他页面请求则保存当前请求并重定向到登录页面;
  3. 如果是post方法的登录页面表单提交请求,则收集用户名/密码登录即可,如果失败了保存错误消息到“shiroLoginFailure”并返回到登录页面;
  4. 如果登录成功了,且之前有保存的请求,则重定向到之前的这个请求,否则到默认的成功页面。
  1. 首先判断用户有没有任意角色,如果没有返回false,将到onAccessDenied进行处理;
  2. 如果用户没有角色,接着判断用户有没有登录,如果没有登录先重定向到登录;
  3. 如果用户没有角色且设置了未授权页面(unauthorizedUrl),那么重定向到未授权页面;否则直接返回401未授权错误码。

八、 Jsp标签

九、 Session Manager 会话管理

十、shiro 注解

1、 @RequiresAuthentication : 表示当前Subject已经通过login进行了身份验证;即 Subject.isAuthenticated() 返回 true
2、@RequiresUser : 表示当前Subject 已经身份验证或者通过记住我登录的
3、@RequiresGuest : 表示当前Subject没有身份验证或通过记住我登陆过,即是游客身份
4、@RequiresRoles(value = { “admin”, “user” }, logical = Logical.AND) : 表示当前 Subject 需要角色 admin和user
5、@RequiresPermissions(value = { “user:a”, “user:b” }, logical = Logical.OR) : 表示当前 Subject 需要权限 user:a 或 user:b



十一、shiro的优点

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/209262.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 上午9:39
下一篇 2026年3月19日 上午9:40


相关推荐

  • Batch Normalization(BN)超详细解析

    Batch Normalization(BN)超详细解析单层视角神经网络可以看成是上图形式 对于中间的某一层 其前面的层可以看成是对输入的处理 后面的层可以看成是损失函数 一次反向传播过程会同时更新所有层的权重 W1 W2 WL 前面层权重的更新会改变当前层输入的分布 而跟据反向传播的计算方式 我们知道 对 Wk 的更新是在假定其输入不变的情况下进行的 如果假定第 k 层的输入节点只有 2 个 对第 k 层的某个输出节点而言 相当于一个线性模型 y w1x1 w2x

    2026年3月18日
    3
  • JavaScript 模块化编程

    JavaScript 模块化编程简介 模块化就是 js 与 js 之间的调用 类似于 Java 类与类之间的调用 使用模块化可以使项目结构更加清晰明了 代码更加优雅 es5 写法 demo1 js 定义方法 consthello function return hello constok function return ok 指定哪些方法可以被调用 module exports hello ok demo2 js 引入要调用的文件 constm require demo1

    2026年3月17日
    1
  • c语言中的三目运算符是_三目运算符试题

    c语言中的三目运算符是_三目运算符试题转载自:impluseC++条件运算符a?b:c;是右结合的,但是这个右结合要怎么理解呢?对于a?b:c?d:e;这样的表达式如果按照右结合来解读的话,那不应该是先运算c,然后返回d或者e,返回后再参与到a?b:d/e;这样的运算的吗?但实际代码的编译测试的结果显然大家都已经知道并非如此,是先计算a,或者返回b,或者返回(c?d…

    2026年4月14日
    5
  • jspdf用法

    jspdf用法介绍一下纯 jspdf 用法 将一个图片列表导出为 pdf 文件 根据图片宽高计算在 pdf 中的位置 jsPDF 是一个基于 HTML5 的客户端解决方案 用于生成各种用途的 PDF 文档 官网地址 https rawgit com MrRio jsPDF master docs 1 安装 npminstalljs 引入 importjsPDFf jspdf 3 使用 letpdf newjsPDF p pt pdfX pdfY 第一

    2026年3月19日
    2
  • Google EventBus 使用详解

    Google EventBus 使用详解EventBus是Google.Guava提供的消息发布-订阅类库,它实现了观察者设计模式,消息通知负责人通过EventBus去注册/注销观察者,最后由消息通知负责人给观察者发布消息。首先使用 maven 依赖:<!– https://mvnrepository.com/artifact/com.google.guava/guava –> <dependenc…

    2022年6月17日
    124
  • Linux 源码编译Python 3.6[通俗易懂]

    Linux 源码编译Python 3.6

    2022年3月3日
    40

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号