Shiro 框架基本使用

文章目录

  • Shiro框架介绍
  • Shiro 基本使用
    • SimpleAccountRealm
    • IniRealm
    • JdbcRealm
    • CustomRealm(自定义Realm)

Shiro框架介绍

Apache Shiro是一个强大且易用的Java安全框架,它执行身份验证、授权、密码和会话管理。Shiro框架通过其三个核心组件:Subject、SecurityManager和Realms,提供了一个通用的安全认证框架。

Shiro官方:http://shiro.apache.org

Shiro的核心架构图

image.png

Shiro 基本使用

认证流程:

image.png

授权流程:

image.png

SimpleAccountRealm

认证代码:

@Test
public void authen() {//认证的发起者(subject),   SecurityManager,   Realm//1. 准备Realm(基于内存存储用户信息)SimpleAccountRealm realm = new SimpleAccountRealm();realm.addAccount("admin", "admin", "超级管理员", "商家");//2. 准备SecurityManagerDefaultSecurityManager securityManager = new DefaultSecurityManager();//3. SecurityManager和Realm建立连接securityManager.setRealm(realm);//4. subject和SecurityManager建立联系SecurityUtils.setSecurityManager(securityManager);//5. 声明subjectSubject subject = SecurityUtils.getSubject();//6. 发起认证subject.login(new UsernamePasswordToken("admin", "admin"));// 如果认证时,用户名错误,抛出:org.apache.shiro.authc.UnknownAccountException异常// 如果认证时,密码错误,抛出:org.apache.shiro.authc.IncorrectCredentialsException://7. 判断是否认证成功System.out.println(subject.isAuthenticated());//8. 退出登录后再判断//        subject.logout();//        System.out.println("logout方法执行后,认证的状态:" + subject.isAuthenticated());//9. 授权是在认证成功之后的操作!!!// SimpleAccountRealm只支持角色的授权System.out.println("是否拥有超级管理员角色:" + subject.hasRole("超级管理员"));subject.checkRole("商家");// check方法校验角色时,如果没有指定角色,会抛出异常:org.apache.shiro.authz.UnauthorizedException: Subject does not have role [角色信息]
}

IniRealm

基于文件存储用户名、密码、角色等信息

准备一个.ini文件,存储用户信息,并且IniRealm支持权限校验

[users]
username=password,role1,role2
admin=admin,超级管理员,运营
[roles]
role1=perm1,perm2
超级管理员=user:add,user:update,user:delete

代码:

@Test
public void authen(){//1. 构建IniRealmIniRealm realm = new IniRealm("classpath:shiro.ini");//2. 构建SecurityManager绑定RealmDefaultSecurityManager securityManager = new DefaultSecurityManager();securityManager.setRealm(realm);//3. 基于SecurityUtils绑定SecurityManager并声明subjectSecurityUtils.setSecurityManager(securityManager);Subject subject = SecurityUtils.getSubject();//4. 认证操作subject.login(new UsernamePasswordToken("admin","admin"));//5. 角色校验// 超级管理员System.out.println(subject.hasRole("超级管理员"));subject.checkRole("运营");//6. 权限校验System.out.println(subject.isPermitted("user:update"));// 如果没有响应的权限,就抛出异常:UnauthorizedException: Subject does not have permission [user:select]subject.checkPermission("user:delete");
}

JdbcRealm

基于数据库存储用户名、密码、角色等信息。

用户认证、授权时推荐的表结构设计,经典五张表!

image.png

代码:

@Test
public void authen(){//1. 构建IniRealmJdbcRealm realm = new JdbcRealm();DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql:///shiro");dataSource.setUsername("root");dataSource.setPassword("root");realm.setDataSource(dataSource);realm.setPermissionsLookupEnabled(true);//2. 构建SecurityManager绑定RealmDefaultSecurityManager securityManager = new DefaultSecurityManager();securityManager.setRealm(realm);//3. 基于SecurityUtils绑定SecurityManager并声明subjectSecurityUtils.setSecurityManager(securityManager);Subject subject = SecurityUtils.getSubject();//4. 认证操作subject.login(new UsernamePasswordToken("admin","admin"));//5. 授权操作(角色)System.out.println(subject.hasRole("超级管1理员"));//6. 授权操作(权限)System.out.println(subject.isPermitted("user:add"));}

SQL构建代码

DROP TABLE IF EXISTS `roles_permissions`;
CREATE TABLE `roles_permissions` (`id` int(11) NOT NULL AUTO_INCREMENT,`permission` varchar(128) NOT NULL,`role_name` varchar(128) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;-- ----------------------------
-- Records of roles_permissions
-- ----------------------------
INSERT INTO `roles_permissions` VALUES ('1', 'user:add', '超级管理员');
INSERT INTO `roles_permissions` VALUES ('2', 'user:update', '超级管理员');
INSERT INTO `roles_permissions` VALUES ('3', 'user:select', '运营');-- ----------------------------
-- Table structure for `users`
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(32) NOT NULL,`password` varchar(32) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES ('1', 'admin', 'admin');-- ----------------------------
-- Table structure for `user_roles`
-- ----------------------------
DROP TABLE IF EXISTS `user_roles`;
CREATE TABLE `user_roles` (`id` int(11) NOT NULL AUTO_INCREMENT,`role_name` varchar(128) NOT NULL,`username` varchar(32) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;-- ----------------------------
-- Records of user_roles
-- ----------------------------
INSERT INTO `user_roles` VALUES ('1', '超级管理员', 'admin');
INSERT INTO `user_roles` VALUES ('2', '运营', 'admin');

CustomRealm(自定义Realm)

仿照JdbcRealm实现一个自定义的Realm对象

  • 声明POJO类,继承AuthorizingRealm
      public class CustomRealm extends AuthorizingRealm {……………………}
    
  • 重写doGetAuthenticationInfo方法(认证)
      /*** 认证方法,只需要完成用户名校验即可,密码校验由Shiro内部完成* @param token  用户传入的用户名和密码* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//1. 基于Token获取用户名String username = (String) token.getPrincipal();//2. 判断用户名(非空)if(StringUtils.isEmpty(username)){// 返回null,会默认抛出一个异常,org.apache.shiro.authc.UnknownAccountExceptionreturn null;}//3. 如果用户名不为null,基于用户名查询用户信息User user = this.findUserByUsername(username);//4. 判断user对象是否为nullif(user == null){return null;}//5. 声明AuthenticationInfo对象,并填充用户信息SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),"CustomRealm!!");//6. 返回inforeturn info;}// 模拟数据库操作private User findUserByUsername(String username) {if("admin".equals(username)){User user = new User();user.setId(1);user.setUsername("admin");user.setPassword("admin");return user;}return null;}
    
  • 重写doGetAuthenticationInfo方法(密码加密加盐)
      {HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();matcher.setHashAlgorithmName("MD5");matcher.setHashIterations(1024);this.setCredentialsMatcher(matcher);}/*** 认证方法,只需要完成用户名校验即可,密码校验由Shiro内部完成* @param token  用户传入的用户名和密码* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//1. 基于Token获取用户名String username = (String) token.getPrincipal();//2. 判断用户名(非空)if(StringUtils.isEmpty(username)){// 返回null,会默认抛出一个异常,org.apache.shiro.authc.UnknownAccountExceptionreturn null;}//3. 如果用户名不为null,基于用户名查询用户信息User user = this.findUserByUsername(username);//4. 判断user对象是否为nullif(user == null){return null;}//5. 声明AuthenticationInfo对象,并填充用户信息SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),"CustomRealm!!");// 设置盐!info.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt()));//6. 返回inforeturn info;}// 模拟数据库操作private User findUserByUsername(String username) {if("admin".equals(username)){User user = new User();user.setId(1);user.setUsername("admin");user.setPassword("1ebc4dcaf1e21b814ece65f27531f1a9");user.setSalt("weruiothergjkdfnbgjkdfngjkdf");return user;}return null;}
    
  • 重写doGetAuthorizationInfo方法(授权)
    // 授权方法,授权是在认证之后的操作
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//1. 获取认证用户的信息User user = (User) principals.getPrimaryPrincipal();//2. 基于用户信息获取当前用户拥有的角色。Set<String> roleSet = this.findRolesByUser();//3. 基于用户拥有的角色查询权限信息Set<String> permSet = this.findPermsByRoleSet(roleSet);//4. 声明AuthorizationInfo对象作为返回值,传入角色信息和权限信息SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();info.setRoles(roleSet);info.setStringPermissions(permSet);//5. 返回return info;
    }private Set<String> findPermsByRoleSet(Set<String> roleSet) {Set<String> set = new HashSet<>();set.add("user:add");set.add("user:update");return set;
    }private Set<String> findRolesByUser() {Set<String> set = new HashSet<>();set.add("超级管理员");set.add("运营");return set;
    }
    

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务是个坏主意吗?

曾几何时&#xff0c;我记得我的手指疯狂地敲打键盘&#xff0c;与庞大而杂乱的代码库搏斗。那是巨石的时代&#xff0c;代码就像古老的城堡一样&#xff0c;由一块块石头砌成一个令人印象深刻的庞然大物。 几年过去了&#xff0c;时代变了。开发人员口中的流行语变成了“微服…

Eclipse如何打开debug变量窗口

今天笔者在使用Eclipse调试的时候&#xff0c;发现没有变量&#xff08;Variables&#xff09;监视窗口&#xff0c;真是头痛得很&#xff0c;最后摸索出一套显示变量窗口的操作如下&#xff1a; 点击other&#xff0c;找到Variables并点击 最后调试代码&#xff0c;调试后如图…

【小知识送书2】从不了解用户画像,到用画像数据赋能业务看这一本书就够了丨《用户画像:平台构建与业务实践》

⭐简单说两句⭐ 作者&#xff1a;后端小知识 CSDN个人主页&#xff1a;后端小知识 &#x1f50e;GZH&#xff1a;后端小知识 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 简单说两句 &#x1f381;本次送书1~3本取决于阅读量&#xff0c;阅…

springboot整合aop,实现日志操作

前言&#xff1a; 整合之前&#xff0c;我们要明白aop是什么&#xff0c;为什么要用aop&#xff0c;aop能帮我们做什么。 答&#xff1a;AOP是面向切面编程&#xff08;Aspect-Oriented Programming&#xff09;的简称&#xff0c;它是一种编程思想&#xff0c;旨在在面向对象…

虹科方案 | LIN/CAN总线汽车零部件测试方案

文章目录 摘要一、汽车零部件测试的重要性&#xff1f;二、虹科的测试仿真工具如何在汽车零部件测试展露头角&#xff1f;三、应用场景**应用场景1&#xff1a;方向盘开关的功能测试****应用场景2&#xff1a;各类型电机的控制测试****应用场景3&#xff1a;RGB氛围灯的功能测试…

win系统环境搭建(六)——Windows安装nginx

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;六&#xff09;——Windows安装nginx 本系列windows环境搭建开始讲解如何给win系统搭建环境&#xff0c;本人所用系统是腾讯云服务器的Windows Server 2022&#xff0c;你可以理解成就是你用的windows10…

建立表使用约束

1.建立表 二、使用约束 1.NOT NULL 非空约束&#xff0c;规定某个字段不能为空&#xff0c;NOT NULL 约束强制列不接受 NULL 值。 NOT NULL 约束强制字段始终包含值。这意味着&#xff0c;如果不向字段添加值&#xff0c;就无法插入新记录或者更新记录。下面的 SQL 强制表&qu…

最小二乘法的实现与线性回归的应用

1. 简介 简单线性回归中&#xff0c;您有一个因变量y和一个自变量X。该模型可以表示为&#xff1a; y m x b ymxb ymxb 其中 x x x: 自变量 y y y: 因变量 m m m: 斜率 b b b: 截距 最小二乘法是回归分析中用于估计线性回归模型参数的标准方法。它可以最小化误差的平方和&…

LVS+Haproxy

LVSHaproxy 一、Haproxy简介1.1、Haproxy应用分析1.2、Haproxy的特性1.3、常见负载均衡策略1.4、LVS、Haproxy、Nginx区别1.5、 Haproxy的优点1.6、常见的Web集群调度器 二、Haproxy部署实例四、日志定义优化 一、Haproxy简介 Haproxy 是一个使用C语言编写的自由及开放源代码软…

mysql odbc驱动安装

到官网下载对应版本的驱动包 可以选择对应版本&#xff0c;建议使用最新版本即可 查看powerDesigner对应的位数&#xff0c;位数对应不上的话&#xff0c;会找不到 powerDesigner 可以参考&#xff1a;powerDesigner安装 我这里装的是32位的 下载对应版本的即可 下载完成&a…

深入理解Kubernetes Pod调试

调试运行中的容器和Pod不像直接调试进程那么容易&#xff0c;本文介绍了通过临时容器共享命名空间的方式调试业务容器进程的方法。原文: Debugging Kubernetes Pods: Deep Dive ZanUnsplash 调试pod最简单的方法是在有问题的pod中执行命令&#xff0c;并尝试排除故障。这种方法…

软件定制开发的优势与步骤|APP搭建|小程序

软件定制开发的优势与步骤|APP搭建|小程序 定制开发的优势&#xff1a; 1. 满足特定需求&#xff1a;定制开发可以根据客户的实际需求进行设计和开发&#xff0c;使得软件系统能够更好地满足客户的业务目标。 2. 优化用户体验&#xff1a;通过深入了解客户的需求&#xff0c;定…

视频监控管理平台/视频汇聚/视频云存储EasyCVR安全检查的相关问题及解决方法3.0

智能视频监控系统/视频云存储/集中存储/视频汇聚平台EasyCVR具备视频融合汇聚能力&#xff0c;作为安防视频监控综合管理平台&#xff0c;它支持多协议接入、多格式视频流分发&#xff0c;视频监控综合管理平台EasyCVR支持海量视频汇聚管理&#xff0c;可应用在多样化的场景上&…

若依前端使用

初始化页面时&#xff0c;路由上加参数 1. 多个菜单对应一个页面&#xff0c;默认查询的数据状态不一样 vue 页面上 通过 debugger; 查看所有的参数&#xff0c; 最后取到了 2. Vue warn]: Error in callback for immediate watcher “fileList”: “TypeError: Cannot read p…

双系统ubuntu20.04(neotic版本)从0实现Gazebo仿真slam建图

双系统ubuntu20.04(neotic版本)从0实现Gazebo仿真slam建图 昨晚完成了ROS的多机通讯&#xff0c;还没来得及整理相关操作步骤&#xff0c;在进行实际小车的实验之前&#xff0c;还是先打算在仿真环境中进行测试&#xff0c;熟悉相关的操作步骤&#xff0c;计划通过虚拟机&…

【深度学习】 Python 和 NumPy 系列教程(九):NumPy详解:1、创建数组的n种方式

目录 一、前言 二、实验环境 三、NumPy 0. 多维数组对象&#xff08;ndarray&#xff09; a. 多维数组的属性 1. 创建数组 a. 使用numpy.array函数&#xff1a; b. 使用numpy.zeros函数 c. 使用numpy.ones函数 d. 使用numpy.arange函数 e. 使用numpy.linspace函数 …

2023Q2全球可穿戴腕带出货量达 4400 万台

全球可穿戴设备市场在2023年第二季度继续保持增长态势&#xff0c;总出货量达到了4400万台&#xff0c;同比增长了6%。这一增长得益于消费者对于可穿戴设备的需求不断增加&#xff0c;以及不同细分市场的需求反弹。 根据市场研究机构 Canalys 的最新报告&#xff0c;全球可穿戴…

Android EditText筛选+选择功能开发

在日常开发中经常会遇到这种需求&#xff0c;EditText既需要可以筛选&#xff0c;又可以点击选择。这里筛选功能用的是AutoCompleteTextView&#xff0c;选择功能使用的是第三方库https://github.com/kongzue/DialogX。 Android AutoCompleteTextView(自动完成文本框)的基本使用…

【物联网】简要解释RTK(Real-Time Kinematic)>>实时动态差分定位

引言&#xff1a; RTK&#xff08;Real-Time Kinematic&#xff09;技术是一种基于差分GPS的高精度定位技术&#xff0c;它通过实时通信和数据处理&#xff0c;能够提供厘米级甚至亚米级的定位精度。RTK技术在许多领域都得到了广泛应用&#xff0c;如测绘、航空航天、农业等。本…

详解Nacos和Eureka的区别

文章目录 Eureka是什么Nacos是什么Nacos的实现原理 Nacos和Eureka的区别CAP理论连接方式服务异常剔除操作实例方式自我保护机制 Eureka是什么 Eureka 是Spring Cloud 微服务框架默认的也是推荐的服务注册中心, 由Netflix公司与2012将其开源出来,Eureka基于REST服务开发,主要用…