当前位置: 首页 > news >正文

Shiro+SpringBoot权限实战:认证授权缓存全搞定

Shiro+SpringBoot权限实战:认证授权缓存全搞定

目录

  • 1.shiro的相关概念——核心框架
  • 2.springboot整合shiro环境搭建
    • 2.1.springboot的创建
    • 2.2. 引入thymeleaf模板
  • 3.shiro中的认证和授权
    • 3.1 认证开发
    • 3.2 自定义Realm
      • 1.shiro提供的Realm
      • 2.根据认证源码认证使用的是SimpleAccountRealm
    • 3.3.使用MD5+Salt+Hash
      • 1.自定义md5+salt的realm
      • 2.使用md5+salt 认证
    • 4 .shiro中的授权
      • 4.1授权的相关概念
      • 4.2shiro编程实现方式
        • 1.realm的实现
  • 4.整合SpringBoot项目实战
    • 4.1 整合思路
    • 4.2配置环境
    • 4.3常见的过滤器
    • 4.4 认证功能和退出的实现
    • 4.5MD5、Salt的认证实现
    • 4.6权限的实现
      • 1.页面资源授权
      • 2.代码方式授权
      • 3.方法调用授权
      • 4.授权数据持久化
      • 5.创建实体类
      • 6.创建dao方法
      • 7.mapper实现
      • 8.Service接口
      • 9.Service实现
      • 10.修改自定义realm
  • 5.使用CacheManager
    • 5.1使用shiro中默认EhCache实现缓存
  • 6、Shiro整合springboot的redis实现
    • 6.1 写ShiroCacheManager实现类
    • 6.2 ShiroCache真正的缓存实现类
    • 6.3 ByteSource的实现类
    • 6.4 对CustomerRealm中的ByteSource进行替换
  • 7.Shiro整合springboot之thymeleaf权限控制
    • 1.引入扩展依赖
    • 2.常见权限控制标签使用
    • 4.加入shiro的方言配置

1.shiro的相关概念——核心框架

  • Subject :为主体信息,访问的用户或者运行的程序
  • SecurityManager即安全管理器,对全部的subject进行安全管理。同时:SecurityManager是一个接口,继承了Authenticator, Authorizer, SessionManager这三个接口。
  • Authenticator即认证器
  • Authorizer即授权器
  • Realm即领域,相当于datasource数据源,securityManager进行安全认证需要通过Realm获取用户权限数据
  • sessionManager即会话管理

2.springboot整合shiro环境搭建

1.springboot的创建

  • 1.右击文件名进入module中

  • 选择spring Initializr

  • 最后选择spring web

2. 引入thymeleaf模板

详细文档:[[(62条消息) Thymeleaf模板引擎详细介绍_AE86-打破常规的博客-CSDN博客_thymeleaf模板引擎

<!--thymeleaf模板--><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring5</artifactId></dependency><dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-java8time</artifactId></dependency>

Thymeleaf简单表达式:

  • 变量表达式: ${…}
  • 选择变量表达式: *{…}
  • 消息表达式: #{…}
  • 链接网址表达式: @{…}
  • 片段表达式: ~{…}

示例代码:

<spanth:text="${book.author.name}">:获取name这个变量的值赋值给text ...<spanth:text="*{title}">...</span><spanth:text="*{price}">...</span><ath:href="@{user/index}"></a></div>

3.shiro中的认证和授权

  • 认证流程

3.1 认证开发

  • 1.引入jar包
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.5.3</version></dependency>
  • 2.引入shiro配置文件

配置文件:名称随意,以 .ini 结尾,放在 resources 目录下

[users] zhangsan=123456 lisi=456789 huang=ming
  • 开发认证代码
packagecom.huang.config;importorg.apache.shiro.SecurityUtils;importorg.apache.shiro.authc.IncorrectCredentialsException;importorg.apache.shiro.authc.UnknownAccountException;importorg.apache.shiro.authc.UsernamePasswordToken;importorg.apache.shiro.mgt.DefaultSecurityManager;importorg.apache.shiro.realm.text.IniRealm;importorg.apache.shiro.subject.Subject;/** * @author * @version 1.0 */publicclassmyShiroConfig{publicstaticvoidmain(String[]args){//1.创建安全管理器对象DefaultSecurityManagersecurityManager=newDefaultSecurityManager();//2.给安全管理器设置realmsecurityManager.setRealm(newIniRealm("classpath:shiro.ini"));//3.SecurityUtils给全局安全工具类设置安全管理器SecurityUtils.setSecurityManager(securityManager);//4.关键对象subject主体Subjectsubject=SecurityUtils.getSubject();//5.创建令牌UsernamePasswordTokentoken=newUsernamePasswordToken("huang","xing");//6.登入认证try{subject.login(token);System.out.println("认证成功");}catch(UnknownAccountExceptione){System.out.println("用户名错误");}catch(IncorrectCredentialsExceptione){System.out.println("密码错误");}}}
  • 4.常见的异常类型
DisabledAccountException(帐号被禁用)LockedAccountException(帐号被锁定)ExcessiveAttemptsException(登录失败次数过多)ExpiredCredentialsException(凭证过期)等

3.2 自定义Realm

  • 认证:
1.最终执行用户名比较是 在SimpleAccountRealm类 的 doGetAuthenticationInfo 方法中完成用户名校验2.最终密码校验是在AuthenticatingRealm类 的 assertCredentialsMatch方法 中
  • 总结:
AuthenticatingRealm认证:realm doGetAuthenticationInfAuthorizingRealm授权:realm doGetAuthorizationInfo
1.shiro提供的Realm

2.根据认证源码认证使用的是SimpleAccountRealm

  • 自定义reaml代码:
packagecom.huang.config.Reaml;importorg.apache.shiro.authc.AuthenticationException;importorg.apache.shiro.authc.AuthenticationInfo;importorg.apache.shiro.authc.AuthenticationToken;importorg.apache.shiro.authc.SimpleAuthenticationInfo;importorg.apache.shiro.authz.AuthorizationInfo;importorg.apache.shiro.realm.AuthorizingRealm;importorg.apache.shiro.realm.SimpleAccountRealm;importorg.apache.shiro.subject.PrincipalCollection;/** * @author * @version 1.0 */publicclassTestRemlextendsAuthorizingRealm{@Override//授权protectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionprincipalCollection){returnnull;}@Override//认证protectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationTokenauthenticationToken)throwsAuthenticationException{//获取用户名Stringprincipal=(String)authenticationToken.getPrincipal();//假设username,password是从数据库获得的信息Stringusername="huang";Stringpassword="123456";if(username.equals(principal)){//参数1:返回数据库中正确的用户名//参数2:返回数据库中正确密码//参数3:提供当前realm的名字 this.getName();SimpleAuthenticationInfoinfo=newSimpleAuthenticationInfo(username,password,this.getName());returninfo;}returnnull;}}

3.3.使用MD5+Salt+Hash

  • 作用:一般用来加密或者签名(校验和)
  • 特点:MD5算法不可逆如何内容相同无论执行多少次md5生成结果始终是一致

网络上提供的MD5在线解密一般是用穷举的方法

  • 生成结果:始终是一个16进制32位长度字符串
  • MD5的基本使用
packagecom.lut.test;importorg.apache.shiro.crypto.hash.Md5Hash;publicclassTestShiroMD5{publicstaticvoidmain(String[]args){//使用md5Md5Hashmd5Hash=newMd5Hash("123");System.out.println(md5Hash.toHex());//使用MD5 + salt处理Md5Hashmd5Hash1=newMd5Hash("123","X0*7ps");System.out.println(md5Hash1.toHex());//使用md5 + salt + hash散列(参数代表要散列多少次,一般是 1024或2048)Md5Hashmd5Hash2=newMd5Hash("123","X0*7ps",1024);System.out.println(md5Hash2.toHex());}}
1.自定义md5+salt的realm
packagecom.huang.config.Reaml;importorg.apache.shiro.authc.AuthenticationException;importorg.apache.shiro.authc.AuthenticationInfo;importorg.apache.shiro.authc.AuthenticationToken;importorg.apache.shiro.authc.SimpleAuthenticationInfo;importorg.apache.shiro.authz.AuthorizationInfo;importorg.apache.shiro.realm.AuthorizingRealm;importorg.apache.shiro.subject.PrincipalCollection;importorg.apache.shiro.util.ByteSource;/** * @author * @version 1.0 */publicclassMd5ReamlextendsAuthorizingRealm{@OverrideprotectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionprincipalCollection){returnnull;}@OverrideprotectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationTokenauthenticationToken)throwsAuthenticationException{Stringprincipal=(String)authenticationToken.getPrincipal();//参数1:数据库用户名//参数2:数据库md5+salt之后的密码//参数3:注册时的随机盐//参数4:realm的名字returnnewSimpleAuthenticationInfo(principal,"a60bb2103d1d2f64653a446700165584",ByteSource.Util.bytes("es@fe24"),this.getName());}}
2.使用md5+salt 认证
packagecom.huang.config;importcom.huang.config.Reaml.Md5Reaml;importorg.apache.shiro.SecurityUtils;importorg.apache.shiro.authc.*;importorg.apache.shiro.authc.credential.CredentialsMatcher;importorg.apache.shiro.authc.credential.HashedCredentialsMatcher;importorg.apache.shiro.mgt.DefaultSecurityManager;importorg.apache.shiro.subject.Subject;/** * @author * @version 1.0 */publicclassMd5ReamlTest{publicstaticvoidmain(String[]args){//设置安全管理器DefaultSecurityManagersecurityManager=newDefaultSecurityManager();//给安全管理器设置reamlMd5Reamlmd5Reaml=newMd5Reaml();//设置md5加密HashedCredentialsMatcherhashedCredentialsMatcher=newHashedCredentialsMatcher("md5");//迭代1024次hashedCredentialsMatcher.setHashIterations(1024);//给reaml设计密码匹配器md5Reaml.setCredentialsMatcher(hashedCredentialsMatcher);securityManager.setRealm(md5Reaml);//把安全管理器交给安全管理器工具类SecurityUtils.setSecurityManager(securityManager);//获取用户Subjectsubject=SecurityUtils.getSubject();UsernamePasswordTokentoken=newUsernamePasswordToken("huang","xing");try{subject.login(token);System.out.println("登入成功");}catch(UnknownAccountExceptione){e.printStackTrace();System.out.println("用户名错误");}catch(IncorrectCredentialsExceptione){e.printStackTrace();System.out.println("密码错误");}}}

4 .shiro中的授权

4.1授权的相关概念

  • 授权流程

  • 基于角色的访问控制

RBAC基于角色的访问控制(Role-Based Access Control)是以角色为中心进行访问控制

if(subject.hasRole("admin")){//操作什么资源}
  • 基于资源的访问

RBAC基于资源的访问控制(Resource-Based Access Control)是以资源为中心进行访问控制

if(subject.isPermission("user:update:01")){//资源实例//对资源01用户具有修改的权限}if(subject.isPermission("user:update:*")){//资源类型//对 所有的资源 用户具有更新的权限}

授权的字符串:

  • 用户创建权限:user:create,或user:create:*
  • 用户修改实例001的权限:user:update:001
  • 用户实例001的所有权限:user: *:001

4.2shiro编程实现方式

  • 编程式
Subjectsubject=SecurityUtils.getSubject();if(subject.hasRole(“admin”)){//有权限}else{//无权限}
  • 注解式
@RequiresRoles("admin")publicvoidhello(){//有权限}
1.realm的实现
packagecom.huang.config.Reaml;importorg.apache.shiro.authc.AuthenticationException;importorg.apache.shiro.authc.AuthenticationInfo;importorg.apache.shiro.authc.AuthenticationToken;importorg.apache.shiro.authc.SimpleAuthenticationInfo;importorg.apache.shiro.authz.AuthorizationInfo;importorg.apache.shiro.authz.SimpleAuthorizationInfo;importorg.apache.shiro.realm.AuthorizingRealm;importorg.apache.shiro.subject.PrincipalCollection;importorg.apache.shiro.util.ByteSource;/** * @author * @version 1.0 */publicclassMd5ReamlextendsAuthorizingRealm{@OverrideprotectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionprincipalCollection){//得到用户名Stringprincipal=(String)principalCollection.getPrimaryPrincipal();//根据身份信息 用户名 获取当前用户的角色信息,以及权限信息SimpleAuthorizationInfosimpleAuthorizationInfo=newSimpleAuthorizationInfo();//假设 admin,user 是从数据库查到的 角色信息simpleAuthorizationInfo.addRole("author");simpleAuthorizationInfo.addRole("user");//假设 ... 是从数据库查到的 权限信息赋值给权限对象simpleAuthorizationInfo.addStringPermission("user:*:01");simpleAuthorizationInfo.addStringPermission("user:delete:*");returnsimpleAuthorizationInfo;}@OverrideprotectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationTokenauthenticationToken)throwsAuthenticationException{Stringprincipal=(String)authenticationToken.getPrincipal();//参数1:数据库用户名//参数2:数据库md5+salt之后的密码//参数3:注册时的随机盐//参数4:realm的名字returnnewSimpleAuthenticationInfo(principal,"a60bb2103d1d2f64653a446700165584",ByteSource.Util.bytes("es@fe24"),this.getName());}}
  • 授权逻辑代码实现:
packagecom.huang.config;import
http://www.jsqmd.com/news/802578/

相关文章:

  • Ubuntu归档与压缩实战:从zip到tar.bz2的格式选择与场景应用
  • c++怎么在Linux下获取文件被最后一次读取的精确纳秒级时间戳【详解】
  • Obsidian效率插件:一键在笔记中打开终端并集成Git与AI工具
  • 2026年信创版资产系统,国产化兼容+集团统一资产管控 - 品牌2026
  • 终极指南:如何用Shortkeys浏览器扩展高效定制键盘快捷键
  • 当数字孪生IOC遇上智能体:智慧水务决策指挥的演进逻辑
  • 苏州蔷薇吊装搬运:专业的苏州起重吊装公司 - LYL仔仔
  • Arcgis 10.2.2 | 攻克License Server启动无响应,从诊断到修复全流程
  • 告别枯燥编程!用OttoBlockly图形化工具让孩子(或你自己)的Otto机器人跳支舞
  • 动物森友会岛屿设计终极指南:用Happy Island Designer打造完美天堂
  • AI中转站:一门靠“信息差”月入百万的生意
  • 为内部工具集成大模型能力如何选择Taotoken的token套餐
  • 社区说|直击 Next 26: 与 Google Cloud 共同探索智能体新时代
  • 突破500ms延迟:flv.js如何实现Web端实时视频会议级传输
  • Windows Server DNS转发器完全教程:安装配置+条件转发+排错
  • 2026年清镇全屋整装与别墅装修一站式定制深度横评:透明化报价如何破局预算黑洞 - 精选优质企业推荐官
  • 终极指南:如何在Windows上无缝安装Android应用
  • 压力传感器高端品牌有哪些?2026年市场格局与产品深度解析 - 品牌推荐大师1
  • 苏州蔷薇吊装搬运:性价比高的苏州起重吊装公司 - LYL仔仔
  • 别再只会调P、I、D了!从传递函数零极点,看懂PID为啥能让你的电机听话
  • 2026年贵阳全屋整装与清镇别墅装修一站式方案深度横评:从毛坯到拎包入住的透明化闭环 - 精选优质企业推荐官
  • Hypermesh拓扑优化实战解析:从C型夹口位移约束到轻量化设计
  • PyTorch模型量化实战:bitsandbytes深度解析与内存优化50%性能提升指南
  • 7个优质免版权音乐平台推荐,免费无侵权,解锁你的专属音乐宝藏 - 拾光而行
  • 【Sora 2视频生成实战指南】:20年AI架构师亲授ChatGPT联动技巧与5大避坑红线
  • VS2019下编译OpenSceneGraph 3.6.5源码,我踩过的那些坑(附完整依赖库配置)
  • B站视频转文字终极指南:3分钟掌握智能内容提取神器
  • 2026高性价比电竞耳机选购攻略 | 主流游戏耳机实测,听声辨位选型指南 - GrowthUME
  • 杭州临安浩雪制冷电器:杭州螺杆机回收选哪家 - LYL仔仔
  • 2026年贵阳全屋整装一站式定制:从预算黑洞到拎包入住的透明化破局指南 - 精选优质企业推荐官