Shiro教程及案例
一、shiro 是什么
shiro 是一个功能强大和易于使用的Java安全框架,为开发人员提供一个直观而全面的解决方案的认证,授权,加密,会话管理。
二、shiro 能干什么
shiro 四个主要的功能
- Authentication:身份认证/登录,验证用户是不是拥有相应的身份;
- Authorization:授权,即权限验证,判断某个已经认证过的用户是否拥有某些权限访问某些资源,一般授权会有角色授权和权限授权;
- SessionManager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的,web 环境中作用是和 HttpSession 是一样的;
- Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
shiro 的其它几个特点
- Web Support:Web支持,可以非常容易的集成到Web环境;
- Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
- Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
- Testing:提供测试支持;
- Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
- Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
三、shiro 架构
从图中我们可以看到不管是任何请求都会经过SecurityManager 拦截并进行相应的处理,shiro 几乎所有的功能都是由 SecurityManager 来管理。
其中:
- Subject:主体,相当与是请求过来的"用户"
- SecurityManager: 是 Shiro 的心脏;所有具体的交互都通过 SecurityManager 进行拦截并控制;它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理
- Authenticator:认证器,负责主体认证的,即确定用户是否登录成功,我们可以使用 Shiro 提供的方法来认证,有可以自定义去实现,自己判断什么时候算是用户登录成功
- Authrizer:授权器,即权限授权,给 Subject 分配权限,以此很好的控制用户可访问的资源
- Realm:一般我们都需要去实现自己的 Realm ,可以有1个或多个 Realm,即当我们进行登录认证时所获取的安全数据来源(帐号/密码)
- SessionManager:为了可以在不同的环境下使用 session 功能,shiro 实现了自己的 sessionManager ,可以用在非 web 环境下和分布式环境下使用
- SessionDAO:对 session 的 CURD 操作
- CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的;
- Cryptography:密码模块,Shiro提高了一些常见的加密组件用于如密码加密/解密的。
四、shiro 的主要功能 - 身份认证
1、Subject 认证
身份认证就是在应用中谁能证明他就是他本人,一般会使用用户名和密码作为认证信息。
2、Subject 认证主体
Subject 认证主体包含两个信息:
- Principals:身份,即用户名
- Credentials:凭证,即密码
** 3、认证流程 **
- 用户发送请求进行 Subject 认证(调用 subject.login(token))
- SecurityManager 会去 Authenticator(认证器)中查找相应的 Realms(可能不止一个)源
- Realms 可以根据不同类型的 Realm 中去查找用户信息,并进行判断是否认证成功
4、快速搭建 helloWorld
1、导包
<dependencies><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.2.4</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.12</version></dependency></dependencies>
2、创建 Realm /resources/shiro.ini
[users]
acey=123456
jack=111
3、进行身份验证
public class HelloWorld {public static void main(String[] args) {
// 加载配置文件,初始化 SecurityManager 工厂Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.shiro.ini");
// 获取 SecurityManager 实例SecurityManager securityManager = factory.getInstance();
// 把 SecurityManager 绑定到 SecurityUtils 中SecurityUtils.setSecurityManager(securityManager);
// 得到当前执行的用户Subject currentUser = SecurityUtils.getSubject();
// 创建 token 令牌,用户名/密码UsernamePasswordToken token = new UsernamePasswordToken("acey", "123456");try {
// 身份验证currentUser.login(token);System.out.println("登录成功");} catch (Exception e) {e.printStackTrace();System.out.println("登录失败");}}
}
四、shiro 的主要功能 - 授权
权限授权就是访问控制,在应用中控制谁能访问哪些资源
1、权限认证中的几个元素
- 权限:即操作某个资源的权限,这些资源可以是某个链接,也可以是某个图片,也可以是对某个模块的数据的 CURL
- 角色:即权限的集合,一个角色可以有多个权限
- 用户:代表访问的用户,即 Subject
2、授权的流程
- 当用户访问应用中的某个资源时,会被 SecurityManager 拦截.
- SecurityManager 会去调用 Authorizer(授权器)
- Authorizer 会根据 Subject 的身份去相应的 Realm 中去查找该 Subject 是否有权限去访问该资源
3、授权实现
- 导包
- 配置 permission(权限) resources/shiro_permission.ini
[main]
authc.loginUrl=/login //表示用户登录失败跳转到 /login
roles.unauthorrizedUrl=/unauthorrized.jsp //表示用户没有对应的访问角色跳转到/unauthorrized.jsp
perms.unauthorrizedUrl=/unauthorrized.jsp //表示用户没有对应的访问权限跳转到/unauthorrized.jsp[users]
acey=123456,role1,role2
jack=123,role1
[roles]
role1=user:select // role1 角色有访问 user:select 的权限
role2=user:add,/delete //role2 角色有访问 user:add 和 /delete 的权限[urls]
/login=anon //表示任何用户都可以访问 /login
/index=authc //表示只有身份认证通过的用户才可以访问 /index
/index=roles[role1,role2...] //表示只有用户含有 role1 role2 ... 角色才可以访问 /index
/index=perms["user:create","/update"] //表示只有用户含有 "user:create" 和"/update"权限才可以访问 /index
/index?=authc //`?`通配符,表示一个字符,如/index1 /indexa /index- (不能匹配/index) ,将符合这种规则的请求进行`authc`拦截
/index*=authc `*`通配符,表示零个或一个或多个字符,如/index1213asd /index /index2 ,将符合这种规则的请求进行`authc`拦截
/index/**=authc `**`表示匹配零个或一个或多个路径,如/index/create /index/create/update/... ,将符合这种规则的请求进行`authc`拦截
/index*/**authc 可以匹配 /index12/create/update/...
3、配置 roles (角色) resources/shiro_role.ini
[users]
acey=123456,role1,role2 //表示有一个用户,用户名是acey,密码为123456,有role1和role2角色
jack=123,role1
4、验证用户角色是否足够
public class RoleTest {// 使用 checkRole 来检验角色时,若权限不足会返回 false@Testpublic void testHasRole() {Subject currentUser= ShiroUtil.login("classpath:shiro_role.ini", "acey", "123456");// Subject currentUser=ShiroUtil.login("classpath:shiro_role.ini", "jack", "123");System.out.println(currentUser.hasRole("role1")?"has role1":"has not role1");currentUser.logout();}// 使用 checkRole 来检验角色时,若权限不足会抛出异常@Testpublic void testCheckRole() {Subject currentUser=ShiroUtil.login("classpath:shiro_role.ini", "acey", "123456");// Subject currentUser=ShiroUtil.login("classpath:shiro_role.ini", "jack", "123");currentUser.checkRole("role1");currentUser.logout();}
}
5、验证用户权限是否足够
public class PermissionTest {// 使用 checkPermission 来检验权限时,若权限不足会返回 false@Testpublic void testIsPermitted() {Subject currentUser= ShiroUtil.login("classpath:shiro_permission.ini", "acey", "123456");System.out.println(currentUser.isPermitted("user:select")?"has user:select":"hsa not user:select");currentUser.logout();}// 使用 checkPermission 来检验权限时,若权限不足会抛出异常@Testpublic void testCheckPermitted() {Subject currentUser=ShiroUtil.login("classpath:shiro_permission.ini", "acey", "123456");// Subject currentUser=ShiroUtil.login("classpath:shiro_permission.ini", "jack", "123");currentUser.checkPermission("user:select");currentUser.logout();}
}
五、ssm 和 shiro 整合
- 导入依赖
- 配置 web.xml(shiro过滤器)
<!-- shiro过滤器定义 --><filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 --> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
3. 编写自己的 Realm(一般权限都是从数据库中查找,所以需要自定义)
public class MyRealm extends AuthorizingRealm{@Resourceprivate UserService userService;/*** 为当前登录的用户授予角色和权限*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//获取用户名String userName=(String)principals.getPrimaryPrincipal();SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();//进行授权角色authorizationInfo.setRoles(userService.getRoles(userName));//进行授权权限authorizationInfo.setStringPermissions(userService.getPermissions(userName));return authorizationInfo;}/***验证当前登录的用户*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String userName=(String)token.getPrincipal();//根据用户名查找用户信息User user=userService.getByUserName(userName);if(user!=null){AuthenticationInfo authcInfo=new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),getName());return authcInfo;}else{return null; }}
}
4、spring 和 shiro 配置整合
...
<!-- 自定义Realm --><bean id="myRealm" class="com.acey.realm.MyRealm"/><!-- 安全管理器 --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="myRealm"/> </bean> <!-- Shiro过滤器 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- Shiro的核心安全接口,这个属性是必须的 --> <property name="securityManager" ref="securityManager"/><!-- 身份认证失败,则跳转到登录页面的配置 --> <property name="loginUrl" value="/index.jsp"/><!-- 权限认证失败,则跳转到指定页面 --> <property name="unauthorizedUrl" value="/unauthor.jsp"/> <!-- Shiro连接约束配置,即过滤链的定义 --> <property name="filterChainDefinitions"> <value> /login=anon/admin*=authc/student=roles[teacher]/teacher=perms["user:create"]</value> </property></bean> <!-- 保证实现了Shiro内部lifecycle函数的bean执行 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!-- 开启Shiro注解 --><bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean>
...
一般角色和权限都存在数据库中,所以我们还可以自定义一个 filter 去自己验证每一个请求的 Subject 是否有权限去访问,这样我们就可以减少对过滤链的维护.比如
<!-- Shiro过滤器 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- Shiro的核心安全接口,这个属性是必须的 --> <property name="securityManager" ref="securityManager"/><!-- 身份认证失败,则跳转到登录页面的配置 --> <property name="loginUrl" value="/index.jsp"/><!-- 权限认证失败,则跳转到指定页面 --> <property name="unauthorizedUrl" value="/unauthor.jsp"/> <!-- Shiro连接约束配置,即过滤链的定义 --> <property name="filterChainDefinitions"> <value> /login=anon/admin*=authc/student=roles[teacher]/teacher=perms["user:create"]</value> </property></bean>
可以改成
<!-- Shiro过滤器 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- Shiro的核心安全接口,这个属性是必须的 --> <property name="securityManager" ref="securityManager"/><!-- 身份认证失败,则跳转到登录页面的配置 --> <property name="loginUrl" value="/index.jsp"/><!-- 权限认证失败,则跳转到指定页面 --> <property name="unauthorizedUrl" value="/unauthor.jsp"/> <property name="ownFilter" class="ownFilter.class"><!-- Shiro连接约束配置,即过滤链的定义 --> <property name="filterChainDefinitions"> <value> /login=anon/**=ownFilter</value> </property></bean>
源码地址:GitHub - Aceysx/shiroDemos: shiro 全套 demo 教程
参考:shiro 瞅完就会用(ssm+shiro) - 简书
Shiro教程及案例相关推荐
- [Shiro教程] Shiro 教程基于SSM(SpringMVC + Spring + Mybatis)EHCache版本
一.Shiro简介 Apache Shiro 是 Java 的一个安全框架.我们经常看到它被拿来和 Spring 的 Security 来对比.大部分人认为 Shiro 比 Security ...
- [Shiro教程] Shiro 教程基于SSM(SpringMVC + Spring + Mybatis)
一.Shiro简介 Apache Shiro 是 Java 的一个安全框架.我们经常看到它被拿来和 Spring 的 Security 来对比.大部分人认为 Shiro 比 Security ...
- 《C# WinForM 实践开发教程》案例×××(2)
<C# WinForM 实践开发教程>案例×××(2): 由于上传限制,必须分卷压缩,请依次下载后解压缩.共有20个文件,合计71.3M. 请耐心下载哦^o^ 转载于:https://bl ...
- Shiro 教程,Shiro教程0.2 下载,Shiro功能修复与升级说明。
2019独角兽企业重金招聘Python工程师标准>>> Shiro + SSM(框架) + Freemarker(jsp)讲解的权限控制Demo,还不赶快去下载? 原文链接:http ...
- Apache Shiro教程
跟开涛学系列: 来自开涛的Apache Shiro教程:http://jinnianshilongnian.iteye.com/blog/2018398 附带的代码例子:https://github. ...
- Shiro 核心功能案例讲解 基于SpringBoot 有源码
Shiro 核心功能案例讲解 基于SpringBoot 有源码 从实战中学习Shiro的用法.本章使用SpringBoot快速搭建项目.整合SiteMesh框架布局页面.整合Shiro框架实现用身份认 ...
- shiro教程(2)- shiro介绍
shiro教程系列 shiro教程(3)-shiro授权 1 shiro介绍 1.1 什么是shiro Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身 ...
- 图书推荐:《ASP.NET.基础教程——C#案例版》
本书结合用C#语言编写的可实际运行的示例代码,讨论了ASP.NET的构架.Web窗体.配置.HTTP管道.故障诊断和错误处理.验证.数据绑定.自定义控件.缓存.状态管理和安全性,阐述用C#构建基于We ...
- phpcmsV9 邮箱配置(含图文教程) - 案例篇
文章目录 phpcmsV9邮箱配置(含图文教程) - 案例篇 前言 · 步骤分析: 步骤 · 开始配置: 相关阅读: phpcmsV9邮箱配置(含图文教程) - 案例篇 前言 · 步骤分析: 注册管理 ...
- 百度地图API的使用教程以及案例
百度地图API的使用教程以及案例 一.注册 百度地图:掌握当前的位置在网页显示位置,插入地图 拖拽,点击事件. 注意:定位 距离 公交 不关心 官网: 点我进入百度地图官网 应用场景:网页插入百度地图 ...
最新文章
- 2015 Multi-University Training Contest 2 1002 Buildings
- 几款高压、高阻电阻测试
- 双轴机械臂串口控制命令开发与测试:STM32F103控制板,简易调试命令集合
- angularjs -- 路由监听
- electron——初探
- Python爬虫 - 解决动态网页信息抓取问题
- Linux日志文件总管——logrotate
- oracle -12169,很奇怪的错误ORA-12169
- linux环境下,Tomcat详细部署步骤
- Mybatis-学习笔记(6)Mybatis的事务管理机制
- php 导出excel接口,PHP实现导出Excel文件
- 转载:IEEE1588 ( PTP ) 协议简介
- 信号与频谱之正弦信号和复信号
- tmp文件删除会影响计算机吗,电脑临时文件能删吗?
- 电脑wifi显示连接上了但是没有网络是怎么回事,手机wifi网络正常,已解决
- 简述Android操作系统和IOS系统的区别;
- godot mysql_Go 每日一库之 godotenv
- hdu 5535 Cake 构造+记忆化搜索
- SEO黑帽技术 - 蜘蛛池原理
- Rosalind Java|Finding a Spliced Motif
热门文章
- IE-LAB网络实验室:HCNP培训机构 HCIE培训中心 HCIE认证培训 HCNA培训 华为面试考试时需要注意什么
- SSIM(结构相似性)-数学公式及python实现
- 质点碰撞和卢瑟福公式
- QTableView固定行显示的问题
- 【科学文献计量】Metaknowledge文献数据分析基础(Record、Citation和RecordCollection对象介绍)
- Windows操作系统装机必备软件,值得收藏!
- 【测试能力提升】Jira 和禅道数据库分析,方便你写周报、写总结、出报告
- jq vue js json转字符串 字符串转json
- 尝试修改smali码破解App
- 鼠标移入移出时定时器加速的原因_2020年值得购买的鼠标有哪些?