Shiro:核心组件、配置类、多Realm场景、自定义拦截器、实战场景

news/2023/6/7 0:02:07

目录

      • Shiro 的核心组件
      • Shiro 认证流程
      • Shiro 授权流程
      • 单 Realm
        • Shiro 登陆认证 SimpleAuthenticationInfo 对象
      • 多 Realm
      • ShiroConfig
        • Shiro过滤器配置 ShiroFilterFactoryBean
        • Shiro自定义过滤器
      • Shiro 过滤器执行链路梳理
      • 代码自取
        • 层级结构
        • Login.java
        • BearerTokenRealm.java
        • ShiroRealm.java

Shiro 的核心组件

Realm、SecurityManager、Subject

Shiro 认证流程

在这里插入图片描述
1、首先调用Subject.login(token)进行登录,其会自动委托给SecurityManager;
2、SecurityManager负责真正的身份验证逻辑;它会委托给Authenticator进行身份验证;
3、Authenticator才是真正的身份验证者,Shiro API中核心的身份认证入口点,此处可以自定义插入自己的实现;
4、Authenticator可能会委托给相应的AuthenticationStrategy进行多Realm身份验证,默认ModularRealmAuthenticator会调用AuthenticationStrategy进行多Realm身份验证;
5、Authenticator会把相应的token传入Realm,从Realm获取身份验证信息,如果没有返回/抛出异常表示身份验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问。

原文链接:https://blog.csdn.net/geejkse_seff/article/details/124345585

Shiro 授权流程

待学习

单 Realm

定义一个 Realm 类继承 AuthorizingRealm,重写 授权 和 认证 两个方法,实现用户的认证授权功能。参考 Demo 代码。

Shiro 登陆认证 SimpleAuthenticationInfo 对象

认证方法中,下面的代码怎么理解:

new SimpleAuthenticationInfo(user, user.getPasswd, getName());

Shiro 会把参数一作为 Subject 主体的信息,通过下面的方式获取:

UserSession user = (UserSession) subject.getPrincipal();

Shiro 会拿 参数二 和 AuthenticationToken 中的 getCredentials() 比较,判断密码的正确性。不匹配则抛出异常。

参考文章

多 Realm

实战:多端用户登入分别认证

ShiroConfig

定义各种 Shiro 配置的 Bean:SecurityManager、DefaultWebSessionManager、ShiroFilterFactoryBean

Shiro过滤器配置 ShiroFilterFactoryBean

一些写法 和 开发注意参考

Shiro自定义过滤器

	ShiroFilterFactoryBena shiroFilter = new ShiroFilterFactoryBena();Map<String, Filter> filter = new HashMap<>();filters.put("authc", new MyFilter());shiroFilter.setFilters(filter);Map<String, String> filterMap = new LinkedHashMap<>();filterMap.put("/login", "anon");filterMap.put("/**", "authc");shiroFilter.setFilterChainDefinitionMap(filterMap);

实战,在过滤器中校验 Token

Shiro 过滤器执行链路梳理

用户登入的动作,Realm里的授权、认证动作,自定义过滤器里的动作,它们的先后顺序是怎么样的,有什么样的调用关系?

在 Shiro 的配置类中,我们通过 ShiroFilterFactoryBean 来添加过滤器,链路的梳理也要在 ShiroFilterFactoryBean 类里找答案。

Shiro过滤器执行链路梳理(认证和授权)

Shiro的Filter机制详解—源码分析

代码自取

只贴了一些核心代码,提供一些思路。

层级结构

在这里插入图片描述

Login.java

登入分为:第一次账号密码登入;之后 Token 登入

/*** 登陆api*/
@RestController
@Slf4j
public class LoginApi {/*** 登录** @param username 用户名* @param password 密码* @return 成功信息*/@PostMapping("/login")public ResponseDTO login(String username, String password) {UsernamePasswordToken token = new UsernamePasswordToken(userId, EncrpytionUtil.encrypt(password));Subject subject = SecurityUtils.getSubject();subject.login(token);UserSession userSession = (UserSession) subject.getPrincipal();ResponseDTO loginResponse = new ResponseDTO();loginResponse.setInfo(userSession.getInfo());return loginResponse;}/*** 登出系统** @return ImsTeResponse*/@GetMapping("/logout")public ResponseDTO logout() {Subject subject = SecurityUtils.getSubject();subject.logout();return new ResponseDTO().success();}}

BearerTokenRealm.java

/*** BearerTokenRealm**/
@Component
@Slf4j
public class BearerTokenRealm extends AuthorizingRealm {/*** ICommDictEntryAppService 字典实体服务*/@Autowiredprivate ICommDictEntryAppService dictEntryAppService;/*** 权限service*/@Autowiredprivate IRoleAppService roleAppService;/*** 员工service*/@Autowiredprivate IOperatorAppService operatorAppService;/*** 外部系统访问授权业务层接口*/private final ICommSystemAccessTokenAppService commSystemAccessTokenService;/*** 登录相关业务层接口*/private final ILoginAppService loginAppService;/*** 构造方法** @param commSystemAccessTokenService 外部系统访问授权业务层接口* @param loginAppService              登录相关业务层接口*/@Autowiredpublic BearerTokenRealm(ICommSystemAccessTokenAppService commSystemAccessTokenService,ILoginAppService loginAppService) {this.commSystemAccessTokenService = commSystemAccessTokenService;this.loginAppService = loginAppService;}/*** 授权* @param authenticationToken* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {UserSession userSession = (UserSession) SecurityUtils.getSubject().getPrincipal();Long operatorId = userSession.getOperatorId();SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();List<CommRoleResponseDTO> roleList = roleAppService.findOperatorRole(operatorId);Set<String> roleSet = roleList.stream().map(CommRoleResponseDTO::getRoleName).collect(Collectors.toSet());simpleAuthorizationInfo.setRoles(roleSet);return simpleAuthorizationInfo;}/*** 认证* @param authenticationToken* @return*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {UserSession userSession = (UserSession) SecurityUtils.getSubject().getPrincipal();if (userSession == null) {throw new MercuryException("用户未登入或Token已过期", 202);}String token = ((BearerToken) authenticationToken).getToken();UserAuthInfo userAuthInfo;try {userAuthInfo = new Gson().fromJson(TextCodec.BASE64URL.decodeToString(token),UserAuthInfo.class);} catch (JsonSyntaxException e) {throw new AuthenticationException("非法请求");}Calendar minTime = Calendar.getInstance();minTime.add(Calendar.MINUTE, -15);Calendar maxTime = Calendar.getInstance();maxTime.add(Calendar.MINUTE, 15);if (userAuthInfo.get_() < minTime.getTimeInMillis()|| userAuthInfo.get_() > maxTime.getTimeInMillis()) {throw new MercuryException("非法请求,token过期", 201);}String userName = userAuthInfo.getUserName();OperatorPO operator = operatorAppService.findByUserId(userName);if (operator == null) {throw new AuthenticationException("用户不存在!");}return new SimpleAuthenticationInfo(loginAppService.buildSessionOperator(operator), token, getName());}@Overridepublic boolean supports(AuthenticationToken token) {return token instanceof BearerToken;}
}

ShiroRealm.java

/*** shirorealm*/
@Slf4j
public class ShiroRealm extends AuthorizingRealm {/*** 登录相关业务层接口*/@Autowiredprivate IOperatorAppService operatorAppService;/*** 登录相关业务层接口*/@Autowiredprivate ILoginAppService loginAppService;/*** 权限service*/@Autowiredprivate IRoleAppService roleAppService;/*** * 授权* @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {UserSession userSession = (UserSession) SecurityUtils.getSubject().getPrincipal();Long operatorId = userSession.getOperatorId();SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();List<CommRoleResponseDTO> roleList = roleAppService.findOperatorRole(operatorId);Set<String> roleSet = roleList.stream().map(CommRoleResponseDTO::getRoleName).collect(Collectors.toSet());simpleAuthorizationInfo.setRoles(roleSet);return simpleAuthorizationInfo;}/*** 认证* @param authenticationToken* @return*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {try {String userId = (String) authenticationToken.getPrincipal();String principal = String.valueOf((char[])authenticationToken.getCredentials());OperatorPO operator = operatorAppService.findById(userId);if (operator == null) {log.error("用户不存在!");throw new IncorrectCredentialsException("用户不存在!");}String passwd = "从数据库获取的用户密码";UserSession userSession = loginAppService.buildSessionOperator(operator);//new SimpleAuthenticationInfo(arg1,arg2,arg3):第一个参数是(UserSession) subject.getPrincipal()的信息;第二个参数,应该传数据库的密码,Shiro会拿 passwd 和 principal比较校验密码;参数三是当前Realm的名字return new SimpleAuthenticationInfo(userSession, passwd, getName());	} catch (IncorrectCredentialsException e) {throw new IncorrectCredentialsException("密码或用户名错误!");}}//重写supports()方法,可以在多个 Realm 场景里使用,见 CustomModularRealmAuthenticator.java@Overridepublic boolean supports(AuthenticationToken token) {return token instanceof UsernamePasswordToken;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-4555273.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

第09章 Go语言并发,Golang并发

并发指在同一时间内可以执行多个任务。并发编程含义比较广泛&#xff0c;包含多线程编程、多进程编程及分布式程序等。本章讲解的并发含义属于多线程编程。 Go 语言通过编译器运行时&#xff08;runtime&#xff09;&#xff0c;从语言上支持了并发的特性。Go 语言的并发通过 g…

深入理解PackageManagerService

原文链接&#xff1a;https://blog.csdn.net/Innost/article/details/47253179 本章主要内容&#xff1a; 详细分析PackageManagerService 1 概述 PackageManagerService是本书分析的第一个核心服务&#xff0c;也是Android系统中最常用的服务之一。它负责系统中Package的管理…

【第二章 Excel数据格式】

Excel数据格式1.Excel数据格式2.更改单元格格式2.1数值型数据的更改2.2文本型数据的更改2.3日期型数据的更改2.4日期型数据、数值型数据->文本型数据1.Excel数据格式 数字、文本和日期是最常用的三种数据格式&#xff0c; 数字一般右对齐&#xff0c;方便观测数据位数&am…

《Java并发编程实战》【第三部分 活跃性、性能与测试】

文章目录第10章 避免活跃性危险10.1 死锁10.1.1 锁顺序死锁10.1.2 动态的锁顺序死锁10.1.3 在协作对象之间发生的死锁10.1.4 开放调用10.1.5 资源死锁10.2 死锁的避免与诊断10.2.1 支持定时的锁10.2.2 通过线程转储信息来分析死锁10.3 其他活跃危险10.3.1 饥饿10.3.2 糟糕的响应…

Java SE 复习

目录 目录 一、基础 二、数组 三、面向对象 1、杂项 2、封装 3、构造器&#xff08;构造方法&#xff09; 4、继承 5、多态 6、包装类 7、设计模式 1、单例设计模式 8、代码块 9、抽象方法与抽象类 10、接口 11、内部类 四、异常类 五、多线程 1、多线程的创…

Linux的基本命令(常用)

一、Linux 常用目录结构 目录介绍&#xff1a; var&#xff1a;包含在正常操作中被改变的文件&#xff0c;假脱机文件、记录文件、加锁文件、临时文件和页格式化文件等。 home&#xff1a;包含用户的文件&#xff0c;参数设置文件、个性化文件、文档、数据、EMAIL、缓存数据等…

帮助台技术员协助的自助服务

对于帮助台技术员例行电话带来成本高居不下的企业来说&#xff0c;最终用户自助服务是一个伟大的解决方案&#xff0c;允许用户解决自己的IT问题。然而&#xff0c;一些企业仍未部署自助服务。例如&#xff0c;即使在Active Directory中维护每个员工的最新个人资料信息是一件乏…

Vue+Express+MongoDB项目部署至腾讯云服务器

服务器项目部署一、服务器1. 放通接口2. 远程桌面3. 环境搭建4. 运行二、代码三、域名解析前段时间买了腾讯云服务器还有域名&#xff0c;一开始想把自己的个人博客放上去&#xff0c;出于种种原因&#xff0c;一直拖延至今&#xff0c;我就把我的个人操作步骤放置在这里&#…