一、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、认证流程 **

  1. 用户发送请求进行 Subject 认证(调用 subject.login(token))
  2. SecurityManager 会去 Authenticator(认证器)中查找相应的 Realms(可能不止一个)源
  3. 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、授权的流程

  1. 当用户访问应用中的某个资源时,会被 SecurityManager 拦截.
  2. SecurityManager 会去调用 Authorizer(授权器)
  3. Authorizer 会根据 Subject 的身份去相应的 Realm 中去查找该 Subject 是否有权限去访问该资源

3、授权实现

  1. 导包
  2. 配置 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 整合

  1. 导入依赖
  2. 配置 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教程及案例相关推荐

  1. [Shiro教程] Shiro 教程基于SSM(SpringMVC + Spring + Mybatis)EHCache版本

    一.Shiro简介 Apache Shiro 是 Java  的一个安全框架.我们经常看到它被拿来和 Spring  的 Security  来对比.大部分人认为 Shiro  比 Security  ...

  2. [Shiro教程] Shiro 教程基于SSM(SpringMVC + Spring + Mybatis)

    一.Shiro简介 Apache Shiro 是 Java  的一个安全框架.我们经常看到它被拿来和 Spring  的 Security  来对比.大部分人认为 Shiro  比 Security  ...

  3. 《C# WinForM 实践开发教程》案例×××(2)

    <C# WinForM 实践开发教程>案例×××(2): 由于上传限制,必须分卷压缩,请依次下载后解压缩.共有20个文件,合计71.3M. 请耐心下载哦^o^ 转载于:https://bl ...

  4. Shiro 教程,Shiro教程0.2 下载,Shiro功能修复与升级说明。

    2019独角兽企业重金招聘Python工程师标准>>> Shiro + SSM(框架) + Freemarker(jsp)讲解的权限控制Demo,还不赶快去下载? 原文链接:http ...

  5. Apache Shiro教程

    跟开涛学系列: 来自开涛的Apache Shiro教程:http://jinnianshilongnian.iteye.com/blog/2018398 附带的代码例子:https://github. ...

  6. Shiro 核心功能案例讲解 基于SpringBoot 有源码

    Shiro 核心功能案例讲解 基于SpringBoot 有源码 从实战中学习Shiro的用法.本章使用SpringBoot快速搭建项目.整合SiteMesh框架布局页面.整合Shiro框架实现用身份认 ...

  7. shiro教程(2)- shiro介绍

    shiro教程系列 shiro教程(3)-shiro授权 1 shiro介绍  1.1 什么是shiro Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身 ...

  8. 图书推荐:《ASP.NET.基础教程——C#案例版》

    本书结合用C#语言编写的可实际运行的示例代码,讨论了ASP.NET的构架.Web窗体.配置.HTTP管道.故障诊断和错误处理.验证.数据绑定.自定义控件.缓存.状态管理和安全性,阐述用C#构建基于We ...

  9. phpcmsV9 邮箱配置(含图文教程) - 案例篇

    文章目录 phpcmsV9邮箱配置(含图文教程) - 案例篇 前言 · 步骤分析: 步骤 · 开始配置: 相关阅读: phpcmsV9邮箱配置(含图文教程) - 案例篇 前言 · 步骤分析: 注册管理 ...

  10. 百度地图API的使用教程以及案例

    百度地图API的使用教程以及案例 一.注册 百度地图:掌握当前的位置在网页显示位置,插入地图 拖拽,点击事件. 注意:定位 距离 公交 不关心 官网: 点我进入百度地图官网 应用场景:网页插入百度地图 ...

最新文章

  1. 2015 Multi-University Training Contest 2 1002 Buildings
  2. 几款高压、高阻电阻测试
  3. 双轴机械臂串口控制命令开发与测试:STM32F103控制板,简易调试命令集合
  4. angularjs -- 路由监听
  5. electron——初探
  6. Python爬虫 - 解决动态网页信息抓取问题
  7. Linux日志文件总管——logrotate
  8. oracle -12169,很奇怪的错误ORA-12169
  9. linux环境下,Tomcat详细部署步骤
  10. Mybatis-学习笔记(6)Mybatis的事务管理机制
  11. php 导出excel接口,PHP实现导出Excel文件
  12. 转载:IEEE1588 ( PTP ) 协议简介
  13. 信号与频谱之正弦信号和复信号
  14. tmp文件删除会影响计算机吗,电脑临时文件能删吗?
  15. 电脑wifi显示连接上了但是没有网络是怎么回事,手机wifi网络正常,已解决
  16. 简述Android操作系统和IOS系统的区别;
  17. godot mysql_Go 每日一库之 godotenv
  18. hdu 5535 Cake 构造+记忆化搜索
  19. SEO黑帽技术 - 蜘蛛池原理
  20. Rosalind Java|Finding a Spliced Motif

热门文章

  1. IE-LAB网络实验室:HCNP培训机构 HCIE培训中心 HCIE认证培训 HCNA培训 华为面试考试时需要注意什么
  2. SSIM(结构相似性)-数学公式及python实现
  3. 质点碰撞和卢瑟福公式
  4. QTableView固定行显示的问题
  5. 【科学文献计量】Metaknowledge文献数据分析基础(Record、Citation和RecordCollection对象介绍)
  6. Windows操作系统装机必备软件,值得收藏!
  7. 【测试能力提升】Jira 和禅道数据库分析,方便你写周报、写总结、出报告
  8. jq vue js json转字符串 字符串转json
  9. 尝试修改smali码破解App
  10. 鼠标移入移出时定时器加速的原因_2020年值得购买的鼠标有哪些?