shiro认证授权

shiro认证授权

在这里插入图片描述

核心组件介绍

  1. Authentication
      身份认证,验证用户是否拥有相应的身份。
  2. Authorization
      授权/权限校验,验证用户是否拥有某个权限。
  3. Session Mannagement
      会话管理,shiro拥有自己的session(不需要web环境下就能使用)
  4. Cryptography
      加密
  5. Web Support
      web支持,支队web应用提供一些功能。
  6. Caching
      缓存
  7. Concurrentcy
      shiro支持多线程应用的并发验证。即在一个线程开启另一个线程,能把授权自动传播过去。
  8. Testing
      测试支持
  9. Run As
      允许一个用户假装成为另外一个用户的省份进行访问。
  10. Rememeber Me
      记住用户身份

主要使用类

在这里插入图片描述

  1. Subject
      与应用交互的用户。Subject在shiro中是一个接口,定义了很多认证授权的方法,外部程序通过Subject进行认证授权,而Subject通过SecurityManager进行认证授权。Subject相当于一个交互的门面,底层逻辑有SecurityManager执行。
  2. SecurityManager
      安全管理器,所有与安全有关的操作都会经过SecurityManager。是shiro的核心,负责与shiro其他组件进行交互。比如:通过Authenticator进行认证,通过Authorizer进行授权,通过sessionManager进行会话管理。
  3. Realm
      Shiro从Realm获取安全数据。SecurityManager要验证身份或操作权限,需要从Realm获取响应数据来判断。

认证流程

在这里插入图片描述

  1. 创建token令牌,token中有用户提交的认证信息即账号和密码。
  2. Subject.login(token)。Subject实例通常是DelegatingSubject类(或子类)的实例对象。在认证的时候,通过SecurityManager实例来调用securityManager.login(token)方法。
  3. SecurityManager接收到token后,委托Authenticator实例进行认证。Authenticator通过实现类ModularRealmAuthenticator.authenticate(token)方法。ModularRealmAuthenticator在认证过程中会对一个或多个Realm实例进行适配。(可插拔)
  4. 如果配置了多个Realm,ModularRealmAuthenticator会根据配置的AuthenticationStrategy(认证策略)来进行多Realm的认证过程。在Realm被调用后,AuthenticationStrategy将对每一个Realm的结果做出响应。如果只有一个Realm,Realm将直接调用而无需再配置认证策略。
  5. 判断每一个Realm是否都支持提交的token,如果支持,Realm调用getAuthenticationInfo(token),改方法就是对认证的处理。我们通过覆盖Realm的doGetAuthenticationInfo方法来编写我们自定义的认证处理。
  6. shiro中有三种认证策略的具体实现。
    ①AtleastOneSuccessfulStrategy:只要有一个Realm验证成功,则成功。
    ②FirstSuccessfulStrategy:第一个realm验证成功,则成功,后续realm将被忽略。
    ③AllSuccessfulStrategy:所有realm成功,验证才成功。
  7. 补充: 认证失败后抛出的一些异常:
    UnknownAccountException 帐号不存在
    IncorrectCredentialsException 密码错误
    DisabledAccountException 帐号被禁用
    LockedAccountException 帐号被锁定
    ExcessiveAttemptsException 登录失败次数过多
    ExpiredCredentialsException 凭证过期

Realm

  shiro自带的realm接口,CachingRealm负责缓存处理。AuthenticationRealm负责认证,AuthorizingRealm负责授权等。通常用户信息都需要通过数据库里面去取,所有需要自定义Realm,通常自定义的realm继承AuthorizingRealm,认证是重写doGetAuthenticationInfo(AuthenticationToken token)方法,授权是重写doGetAuthorizationInfo(PrincipalCollectionprincipals)方法

自定义Realm中注入的实例为什么要加@Lazy注解

  原因为什么要加@Lazy

  通过将注入的实体类,增加无参构造函数,打dug观察。发现这个这个bean实例化是在registerBeanPostProcessors中。在 refresh 方法的后置处理器注册步骤就已经创建好了。按照IOC容器的初始化流程,一定是先把后置处理器都注册好了,再创建单实例Bean。在这里很明显是后置处理器还没完全处理完,就引发单实例Bean的创建了。
在这里插入图片描述
  解决方案:如何让Realm创建时不立即创建依赖的对象。
  shiro为什么要提早创建Realm?
  Shiro的后置处理器。  shiroEventBusAwareBeanPostProcessor。它依赖了一个EventBus。后面又依赖SecurityManager,SecurityManager依赖Realm。Realm的创建又依赖需要的实例。而实例的创建时由于事务控制增强器话没有创建好,所以无法代理这个Realm依赖的实例,最终注入到Realm的实例就是不带事务的。总结如下:
①ApplicaitonContext的refresh方法要创建BeanPostProcessor。
②ShiroEventBusBeanPostProcessor的创建需要依赖EventBus。
③EventBus创建时需要被AOP增强,触发AOP增强器的创建逻辑。此时AOP增强器有2个,分别是事务控制增强器和shiro的增强器。
④首先创建事务控制的AOP增强器TransactionAttributeSourceAdvisor,由于它定义在配置类中,又触发配置类的创建。
⑤配置类创建时也要被AOP增强,再一次触发AOP增强器的创建逻辑。此时事务控制增强器正在被创建,所以被跳过了。
⑥触发shiro增强器的创建,而shiro增强器又依赖SecurityManager
⑦SecurityManage又依赖authorizer,也就是自定义的Realm
⑧自定义Realm依赖业务实例,触发业务实例的创建。
⑨业务实例创建后要被事务AOP增强,但此时事务控制器还没完全创建好,所以无法代理,导致业务实例不带事务。

@Lazy注解原理

  @Lazy标注在业务实体类上是不可行的。@Lazy要标注在Realm中依赖的业务实体类上。
  。@Lazy要标注在Realm中依赖的业务实体类上后,在dubug可以发现,创建这个业务实体的实际是正常的实例化单例bean的时机。
在这里插入图片描述
  @Lazy 的使用规则和对应的原理:
(1)@Lazy 标注在 Bean 的类上:告诉 IOC 容器,在容器初始化阶段不要实例化我。
(2)@Lazy 标注在其他 Bean 的依赖上:告诉 IOC 容器,在创建这个标注了 @Lazy 的 Bean 时,不要立即处理我标注的这个依赖。

授权

在这里插入图片描述

  1. 调用授权验证方法。Subject.isPermitted() 或者 Subject.hasRole()等。
  2. Subject实例通常是DelegatingSubject类或子类的实例对象。在认证开始时,通过SecurityManager实例来调用securityManager.isPermitted(string)方法或者security.hasRole(string)方法。
  3. SecurityManager委托Authorizer的实例调用响应的授权方法。
  4. 每一个Realm将检查是否实现了相同的Authorizer接口,然后调用Realm自己的相应的授权验证方法。
  5. 使用多个Realm时,不同于认证策略处理方式,授权处理过程中:
    ①当调用Realm出现异常时,立即抛出,结束授权验证
    ②只要一个Realm验证成功,则认为授权成功,立即返回,结束验证。

在shiro中提供了一些好用的注解

// 表示Subject已经通过login身份验证
@RequiresAuthentication  
 
// 表示当前是用户身份
@RequiresUser  

// 表示当是游客身份。
@RequiresGuest  

// 表示当前需要的角色
@RequiresRoles(value={"admin", "user"}, logical= Logical.AND)  

// 表示当前需要的权限
@RequiresPermissions (value={"p:admin", "p:user"}, logical= Logical.OR)

  使用它之前,我们需要开启它的注解,怎么做呢?在ShiroConfig中加入:

@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
    return authorizationAttributeSourceAdvisor;
}

  然后就可以直接使用

@RestController
public class TestController {

    @RequiresPermissions("p:user")
    @RequestMapping("/index")
    public String index(Model model) {
        // 登录成后,即可通过Subject获取登录的用户信息
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        model.addAttribute("user", user);
        return "index --->" + user.getUsername();
    }
}

权限异常捕获

  对于没有权限的情况,想要自定义返回错误,可以通过异常捕获。

@ControllerAdvice
public class ExceptionController {
    @ExceptionHandler(value = AuthorizationException.class)
    public String handleAuthorizationException() {
        return "您当前没有权限访问~ 请联系管理员";
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Shiro框架是一个功能强大的Java安全框架,可以用于认证授权。下面是使用Shiro进行认证授权的基本步骤: 1. 添加Shiro依赖:在你的项目中添加Shiro的相关依赖,可以通过Maven或者Gradle进行引入。 2. 配置Shiro:创建一个Shiro的配置文件(通常是一个ini文件),配置Shiro的一些基本信息,例如Realm、Session管理等。你可以根据你的需求进行配置。 3. 创建Realm:Realm是Shiro用来进行认证授权的核心组件。你需要实现一个自定义的Realm来实现用户的认证授权逻辑。在Realm中,你可以通过重写相应的方法来实现自定义的认证授权逻辑,例如验证用户名密码、查询用户角色和权限等。 4. 认证:在用户登录时,你可以通过调用Shiro提供的Subject.login方法来进行认证。该方法会将用户提交的用户名和密码传递给你自定义的Realm进行验证。如果验证通过,Shiro会将用户信息保存在Session中。 5. 授权:在用户进行操作时,你可以通过调用Shiro提供的Subject.hasRole和Subject.isPermitted方法来进行授权判断。这些方法会根据你在Realm中配置的角色和权限信息进行判断,决定用户是否具有相应的角色或权限。 以上是使用Shiro进行认证授权的基本步骤,你可以根据具体的需求进行定制和扩展。在实际应用中,你还可以通过Shiro提供的其他功能,如RememberMe、Session管理等来增强安全性和用户体验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值