当前位置:   article > 正文

Java---Shiro框架_java shiro

java shiro

第一章   入门概述

1.1 什么是shiro

        Apache Shiro 是一个功能强大且易于使用的 Java 安全(权限)框架。Shiro 可以完成:认证、授权、加密、会话管理、与 Web 集成、缓存 等。借助 Shiro 您可以快速轻地保护任何应用程序——从最小的移动应用程序到最大的 Web 和企业应用程序。

 1.2 为什么要用shiro

        自 2003 年以来,框架格局发生了相当大的变化,因此今天仍然有很多系统在使用Shiro。这与 Shiro 的特性密不可分。

        易于使用:使用 Shiro 构建系统安全框架非常简单。就算第一次接触也可以快速掌握。

        全面:Shiro 包含系统安全框架需要的功能,满足安全需求的“一站式服务”。

        灵活:Shiro 可以在任何应用程序环境中工作。虽然它可以在 Web、EJB 和 IOC 环境中工作,但不需要依赖它们。Shiro 也没有强制要求任何规范,甚至没有很多依赖项。

        强力支持 Web:Shiro 具有出色的 Web 应用程序支持,可以基于应用程序 URL 和Web 协议(例如 REST)创建灵活的安全策略,同时还提供一组 JSP 库来控制页面输出。

        兼容性强:Shiro 的设计模式使其易于与其他框架和应用程序集成。Shiro 与Spring、Grails、Wicket、Tapestry、Mule、Apache Camel、Vaadin 等框架无缝集成。

1.3 Shiro 与 SpringSecurity 的对比

1、Spring Security 基于 Spring 开发,项目若使用 Spring 作为基础,配合 SpringSecurity 做权限更加方便,而 Shiro 需要和 Spring 进行整合开发;

2、Spring Security 功能比 Shiro 更加丰富些,例如安全维护方面;

3、Spring Security 社区资源相对比 Shiro 更加丰富;

4、Shiro 的配置和使用比较简单,Spring Security 上手复杂些;

5、Shiro 依赖性低,不需要任何框架和容器,可以独立运行Spring Security 依赖Spring 容器;

6、shiro 不仅仅可以使用在 web 中,它可以工作在任何应用环境中。在集群会话时 Shiro最重要的一个好处或许就是它的会话是独立于容器的。

1.4 有哪些功能?


(1)Authentication:身份认证/登录,验证用户是不是拥有相应的身份。

(2)Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能进行什么操作,如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限。

(3)Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境,也可以是Web 环境的。

(4)Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储。

(5)Web Support:Web 支持,可以非常容易的集成到Web 环境。

(6)Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率。

(7)Concurrency:Shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去。

(8)Testing:提供测试支持。

(9)“Run As”:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问。

(10)Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

1.5 Shiro架构(外部)

image-20200729114702566

从外部来看Shiro,即从应用程序角度的来观察如何使用Shiro完成工作

Subject:应用代码直接交互的对象是Subject,也就是说Shiro的对外API 核心就是Subject。Subject 代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;与Subject 的所有交互都会委托给SecurityManager;Subject 其实是一个门面,SecurityManager才是实际的执行者

SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且其管理着所有Subject;可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVC中DispatcherServlet的角色

Realm:Shiro从Realm 获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm 得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm 看成DataSource。

1.6  Shiro架构(内部)

image-20200729114720578

  • Subject:任何可以与应用交互的“用户”。
  • SecurityManager:相当于SpringMVC中的DispatcherServlet;是Shiro的心脏;所有具体的交互都通过SecurityManager进行控制;它管理着所有Subject、且负责进行认证、授权、会话及缓存的管理。
  • Authenticator:负责Subject 认证,是一个扩展点,可以自定义实现;可以使用认证策略(Authentication Strategy),即什么情况下算用户认证通过了;
  • Authorizer:授权器、即访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能。
  • Realm:可以有1 个或多个Realm,可以认为是安全实体数据源,即用于获取安全实体的;可以是JDBC 实现,也可以是内存实现等等;由用户提供;所以一般在应用中都需要实现自己的Realm。
  • SessionManager:管理Session 生命周期的组件;而Shiro并不仅仅可以用在Web 环境,也可以用在如普通的JavaSE环境。
  • CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少改变,放到缓存中后可以提高访问的性能。
  • Cryptography:密码模块,Shiro提高了一些常见的加密组件用于如密码加密/解密。

第二章 shiro登录认证

1. 创建数据库
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0 ;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`uid` int ( 11 ) NOT NULL AUTO_INCREMENT,
`uname` varchar ( 32 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`pwd` varchar ( 32 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`sex` varchar ( 2 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL ,
`address` varchar ( 200 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT
NULL ,
`state` int ( 2 ) DEFAULT NULL ,
`salt` varchar ( 32 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL ,
PRIMARY KEY (`uid`) USING BTREE,
UNIQUE INDEX `uname`(`uname`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE =
utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ( 1 , 'admin' , '727d8b2b4c59366d7ace58d4eda4cfee' , ' ' ,
' 河南洛阳 ' , 1 , '9C2AB20283F9450389330033D64686DD' );
INSERT INTO `user` VALUES ( 2 , 'zs' , '83f12ba7c4357b87167e240a22c15248' , ' ' , '
南郑州 ' , 1 , '262F995823C94D1CAE7596B47E8AB657' );
select * from user
2. 创建 web 项目并配置 SSM
完成 user 表的 dao 层和 service 层的书写
3. 创建 MyShiroRealm 继承 AuthorizingRealm
注意:使用 @Component 注解交给 spring 管理
  1. package com.chen.shiro;
  2. import com.chen.bean.User;
  3. import com.chen.service.IUserService;
  4. import org.apache.shiro.authc.AuthenticationException;
  5. import org.apache.shiro.authc.AuthenticationInfo;
  6. import org.apache.shiro.authc.AuthenticationToken;
  7. 4.在spring.xml中配置shiro管理器和自定义的Realm
  8. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  9. import org.apache.shiro.authz.AuthorizationInfo;
  10. import org.apache.shiro.realm.AuthorizingRealm;
  11. import org.apache.shiro.subject.PrincipalCollection;
  12. import org.apache.shiro.util.ByteSource;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.stereotype.Component;
  15. /**
  16. * token 里面是客户端发来的信息(包含输入的用户名 和 密码)
  17. * 自定义Realm,通过mybatis查询数据库的密码和盐值,让shiro进行身份验证
  18. */
  19. @Component
  20. public class MyRealm extends AuthorizingRealm {
  21. @Autowired
  22. IUserService userService;
  23. //shiro 进行授权操作
  24. @Override
  25. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection
  26. principals) {
  27. return null;
  28. }
  29. //shiro 进行认证操作
  30. @Override
  31. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken
  32. token) throws AuthenticationException {
  33. //token 是主体传过来的身份令牌
  34. //1 获取用户身份信息
  35. String uname = token.getPrincipal().toString();
  36. //2 调用业务层获取用户信息(数据库中)
  37. User user = userService.findByUname(uname);
  38. //3 判断并将数据完成封装
  39. if(user!=null){
  40. AuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(
  41. token.getPrincipal(), //令牌身份信息对象
  42. user.getPwd(), //用户数据库的密码
  43. ByteSource.Util.bytes(user.getSalt().getBytes()), //加密时的
  44. 盐值
  45. uname // 用户名
  46. );
  47. return authenticationInfo;
  48. }
  49. return null;
  50. }
  51. }

 4.spring.xml中配置shiro管理器和自定义的Realm

  1. <!--=================shiro相关配置====================-->
  2. <!--配置shiro进行校验时的加密规则-->
  3. <bean id="credentialsMatcher"
  4. class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
  5. <!--加密规则-->
  6. <property name="hashAlgorithmName" value="MD5" />
  7. <!--是否加盐-->
  8. <property name="hashSalted" value="true" />
  9. <!--是否增加哈希算法进行散列-->
  10. <!-- <property name="hashIterations" value="1024" />-->
  11. </bean>
  12. <!--配置自定义Realm-->
  13. <bean id="myRealm" class="com.chen.shiro.MyRealm">
  14. <property name="credentialsMatcher" ref="credentialsMatcher" />
  15. </bean>
  16. <!--配置安全管理器,使用自定义的Realm-->
  17. <bean id="securityManager"
  18. class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
  19. <!--配置自定义的Realm-->
  20. <property name="realm" ref="myRealm" />
  21. </bean>
  22. <!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
  23. <bean id="shiroFilter"
  24. class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  25. <!-- 调用我们配置的权限管理器 -->
  26. <property name="securityManager" ref="securityManager"/>
  27. <!-- 配置拦截后我们的登录请求地址 -->
  28. <property name="loginUrl" value="/loginUI"/>
  29. <!-- 如果您请求的资源不再您的权限范围,则跳转到错误页面 -->
  30. <property name="unauthorizedUrl" value="/error"/>
  31. <!-- 权限配置
  32. anon:任何人都可以访问; authc:必须是登录之后才能进行访问,不包括remember
  33. me;
  34. perms:指定过滤规则,可以自己拓展权限配置; roles:配置角色;
  35. user:登录用户才可以访问,包含remember me; logout:退出
  36. -->
  37. <property name="filterChainDefinitions">
  38. <value>
  39. /=anon
  40. /index = anon
  41. /loginUI = anon
  42. /login = anon
  43. /WEB-INF/view/login.html = anon
  44. /**/*.js=anon
  45. /**/*.css=anon
  46. /**=authc
  47. /**=user
  48. </value>
  49. </property>
  50. </bean>
权限配置
anon :任何人都可以访问;
authc :必须是登录之后才能进行访问,不包括 remember me
perms :指定过滤规则,可以自己拓展权限配置;
roles :配置角色;
user :登录用户才可以访问,包含 remember me
logout :退出

5.web.xml中配置shiro的过滤器

  1. <!-- shiro配置 -->
  2. <filter>
  3. <filter-name>shiroFilter</filter-name>
  4. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filterclass>
  5. <init-param>
  6. <param-name>targetFilterLifecycle</param-name>
  7. <param-value>true</param-value>
  8. </init-param>
  9. </filter>
  10. <filter-mapping>
  11. <filter-name>shiroFilter</filter-name>
  12. <url-pattern>/*</url-pattern>
  13. </filter-mapping>

 6.controller中进行shiro认证

  1. package com.chen.controller;
  2. import com.chen.service.UserService;
  3. import org.apache.shiro.SecurityUtils;
  4. import org.apache.shiro.authc.*;
  5. import org.apache.shiro.authz.annotation.RequiresPermissions;
  6. import org.apache.shiro.authz.annotation.RequiresRoles;
  7. import org.apache.shiro.subject.Subject;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.stereotype.Controller;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.RequestParam;
  12. import org.springframework.web.bind.annotation.ResponseBody;
  13. import javax.servlet.http.HttpSession;
  14. @Controller
  15. public class UserController {
  16. @Autowired
  17. UserService userService;
  18. @RequestMapping("/login")
  19. public String login(String uname, String pwd, HttpSession session) {
  20. System.out.println(uname+"------------------");
  21. //1 获取 Subject 对象
  22. Subject subject = SecurityUtils.getSubject();
  23. //2 封装请求数据到 token 对象中
  24. AuthenticationToken token = new UsernamePasswordToken(uname, pwd);
  25. //3 调用 login 方法进行登录认证
  26. try {
  27. //5.验证主体是否能够登录
  28. subject.login(token);
  29. session.setAttribute("user", token.getPrincipal().toString());
  30. return "main";
  31. } catch (UnknownAccountException e) {
  32. System.out.println("用户名不存在!");
  33. return "login";
  34. } catch (IncorrectCredentialsException e) {
  35. System.out.println("密码错误!");
  36. return "login";
  37. } catch (AuthenticationException e) {
  38. System.out.println("认证失败,不知道出了什么问题");
  39. return "login";
  40. }
  41. }
  42. }

第三章 shirorememberMe功能

Shiro 提供了记住我( RememberMe )的功能,比如访问一些网站时,关闭了浏览器, 下次再打 开时还是能记住你是谁, 下次访问时无需再登录即可访问。
例如:当没有登录时,访问 /main 主页,会被拦截跳转到登录页面。当登录后是可以正常访
/main 的主页的;如果使用了记住我功能,会在浏览器写入 cookie ,关掉浏览器不需要登录即可 直接访问/main
基本流程
1. 首先在登录页面选中 RememberMe 然后登录成功;如果是浏览器登录,一般会 把
RememberMe Cookie 写到客户端并保存下来;
2. 关闭浏览器再重新打开;会发现浏览器还是记住你的;
3. 访问一般的网页服务器端,仍然知道你是谁,且能正常访问;
4. 但是,如果我们访问电商平台时,如果要查看我的订单或进行支付时,此时还 是需要再进行身份认
证的,以确保当前用户还是你。
1. spring.xml 中配置 cookie 的设置和 rememberMe 理器

1.配置记住我功能的cookie设置;

2. 配置记住我功能的管理器;
3. 在安全管理器中引用记住我功能的管理器;
4. 在过滤器中 shiroFilter 配置 rememberMe 的过滤配置( /**=user
  1. <!--=================shiro相关配置====================-->
  2. <!--配置shiro进行校验时的加密规则-->
  3. <bean id="credentialsMatcher"
  4. class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
  5. <!--加密规则-->
  6. <property name="hashAlgorithmName" value="MD5" />
  7. <!--是否加盐-->
  8. <property name="hashSalted" value="true" />
  9. <!--是否增加哈希算法进行散列-->
  10. <!-- <property name="hashIterations" value="1024" />-->
  11. </bean>
  12. <!--配置自定义Realm-->
  13. <bean id="myRealm" class="com.chen.shiro.MyRealm">
  14. <property name="credentialsMatcher" ref="credentialsMatcher" />
  15. </bean>
  16. <!--=================记住我功能相关配置====================-->
  17. <!--记住我功能的cookie设置-->
  18. <bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
  19. <!--设置cookie的属性名-->
  20. <property name="name" value="rememberMe" />
  21. <!--设置cookie存在根目录,可在同一应用服务器内共享-->
  22. <property name="path" value="/" />
  23. <!--通过JavaScript脚本将无法读取到Cookie信息,这样能有效的防止XSS攻击,让网站应用更
  24. 加安全-->
  25. <property name="httpOnly" value="true" />
  26. <!--设置cookie的失效时间为30天-->
  27. <property name="maxAge" value="2592000" />
  28. </bean>
  29. <!--记住我功能的管理器配置-->
  30. <bean id="rememberMeManager"
  31. class="org.apache.shiro.web.mgt.CookieRememberMeManager">
  32. <!--引用cookie设置-->
  33. <property name="cookie" ref="simpleCookie" />
  34. <!--默认AES算法,设置cookie的加密算法,采用的是base64的加密-->
  35. <property name="cipherKey" value="#
  36. {T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" />
  37. </bean>
  38. <!--配置安全管理器,使用自定义的Realm-->
  39. <bean id="securityManager"
  40. class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
  41. <!--配置自定义的Realm-->
  42. <property name="realm" ref="myRealm" />
  43. <!--====引用rememberMe功能管理器====================-->
  44. <property name="rememberMeManager" ref="rememberMeManager" />
  45. </bean>
  46. <!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
  47. <bean id="shiroFilter"
  48. class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  49. <!-- 调用我们配置的权限管理器 -->
  50. <property name="securityManager" ref="securityManager"/>
  51. <!-- 配置拦截后我们的登录请求地址 -->
  52. <property name="loginUrl" value="/loginUI"/>
  53. <!-- 如果您请求的资源不再您的权限范围,则跳转到错误页面 -->
  54. <property name="unauthorizedUrl" value="/error"/>
  55. <!-- 权限配置 -->
  56. <!-- 权限配置
  57. anon:任何人都可以访问; authc:必须是登录之后才能进行访问,不包括remember
  58. me;
  59. perms:指定过滤规则,可以自己拓展权限配置; roles:配置角色;
  60. user:登录用户才可以访问,包含remember me; logout:退出
  61. -->
  62. <property name="filterChainDefinitions">
  63. <value>
  64. /=anon
  65. /index = anon
  66. /loginUI = anon
  67. /login = anon
  68. /WEB-INF/view/login.html = anon
  69. /**/*.js=anon
  70. /**/*.css=anon
  71. /**=authc
  72. /**=user
  73. </value>
  74. </property>
  75. </bean>
2. 页面上添加记住我勾选的复选框按钮,并设置 name 属性 rememberMe
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>登录</title>
  6. </head>
  7. <body>
  8. <div id="content">
  9. <form class="form-horizontal" action="/login" method="post">
  10. <div class="form-group">
  11. <label for="uname" class="col-sm-2 control-label">帐号</label>
  12. <div class="col-sm-10">
  13. <input type="text" name="uname" class="form-control" id="uname"
  14. placeholder="帐号">
  15. </div>
  16. </div>
  17. <div class="form-group">
  18. <label for="pwd" class="col-sm-2 control-label">密码</label>
  19. <div class="col-sm-10">
  20. <input type="password" name="pwd" class="form-control" id="pwd"
  21. placeholder="密码">
  22. </div>
  23. </div>
  24. <div class="form-group">
  25. <div class="col-sm-offset-2 col-sm-10">
  26. <div class="checkbox">
  27. <label>
  28. <input type="checkbox" name="rerememberMe"> 记住我
  29. </label>
  30. </div>
  31. </div>
  32. </div>
  33. <div class="form-group">
  34. <div class="col-sm-offset-2 col-sm-10">
  35. <button type="submit" id="login" class="btn btn-primary">登录
  36. </button>
  37. <a href="/indexUI">去注册</a>
  38. </div>
  39. </div>
  40. </form>
  41. </div>
  42. </body>
  43. </html>
3. 修改 controller ,或者记住我功能是否勾选,认证时添加 记住我标记
1. 配置 boolean 类型的请求参数 rerememberMe ,并设置默认值是 false
2. 在封装 token 时,加入 rerememberMe 标记;

  1. package com.chen.controller;
  2. import com.chen.service.UserService;
  3. import org.apache.shiro.SecurityUtils;
  4. import org.apache.shiro.authc.*;
  5. import org.apache.shiro.authz.annotation.RequiresPermissions;
  6. import org.apache.shiro.authz.annotation.RequiresRoles;
  7. import org.apache.shiro.subject.Subject;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.stereotype.Controller;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.RequestParam;
  12. import org.springframework.web.bind.annotation.ResponseBody;
  13. import javax.servlet.http.HttpSession;
  14. @Controller
  15. public class UserController {
  16. @Autowired
  17. UserService userService;
  18. @RequestMapping("/login")
  19. public String login(String uname, String pwd, @RequestParam(defaultValue = "false") boolean rerememberMe, HttpSession session) {
  20. System.out.println(uname+"------------------");
  21. //1 获取 Subject 对象
  22. Subject subject = SecurityUtils.getSubject();
  23. //2 封装请求数据到 token 对象中
  24. AuthenticationToken token = new UsernamePasswordToken(uname, pwd,rerememberMe);
  25. //3 调用 login 方法进行登录认证
  26. try {
  27. //5.验证主体是否能够登录
  28. subject.login(token);
  29. session.setAttribute("user", token.getPrincipal().toString());
  30. return "main";
  31. } catch (UnknownAccountException e) {
  32. System.out.println("用户名不存在!");
  33. return "login";
  34. } catch (IncorrectCredentialsException e) {
  35. System.out.println("密码错误!");
  36. return "login";
  37. } catch (AuthenticationException e) {
  38. System.out.println("认证失败,不知道出了什么问题");
  39. return "login";
  40. }
  41. }
  42. }
4. 测试 rerememberMe 功能
1. 不登录直接访问主页 /main shiro 会拦截去到登录页;登录后可以正常访问主页 /main
2. 登录时不勾选记住我,关闭浏览器访问主页 /main 还会拦截到登录页;
3. 登录时勾选记住我,关闭浏览器访问主页 /main 可以正常访问;

第四章 shiro的登出

1.在主页设置退出登录的链接

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>主页</title>
  6. <body>
  7. <img src="/img/index.jpg">
  8. <a href="/logout">退出登录</a>
  9. </body>
  10. </html>
2. spring.xml 配置文件中找到 shiro 过滤器,配置登出的 操作
  1. <property name="filterChainDefinitions">
  2. <value>
  3. /=anon
  4. /index = anon
  5. /loginUI = anon
  6. /login = anon
  7. /logout=logout
  8. /WEB-INF/view/login.html = anon
  9. /**/*.js=anon
  10. /**/*.css=anon
  11. /**=authc
  12. /**=user
  13. </value>
  14. </property>

第六章 shiro角色授权认证

1. 在主页设计两个超链接,分别模拟查看用户管理和系统管
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>主页</title>
  6. </head>
  7. <body>
  8. <h2>内容页</h2>
  9. <a href="/loginOut">退出登录</a>
  10. <hr>
  11. <ul>
  12. <li><a href="/user">用户管理</a></li>
  13. <li><a href="/system">系统管理</a></li>
  14. </ul>
  15. </body>
  16. </html>
2. 在控制器中使用 @RequiresRoles("roles") 注解来开启请 求的角色验证
  1. @RequiresRoles("user")
  2. @RequestMapping("/user")
  3. public String user(){
  4. System.out.println("用户管理");
  5. return "userList";
  6. }
  7. @RequiresRoles("admin")
  8. @RequestMapping("/system")
  9. public String system(){
  10. System.out.println("系统管理");
  11. return "system";
  12. }
3. springmvc.xml 中开启 shiro 的注解支持
由于 shiro 注解是在 controller 中配置,所以需要在 springmvc.xml 中配置 shiro 的注解支持;
1. 配置 shiro bean 生命周期处理器
2. 配置自动创建代理;
3. 开启 shiro 注解的支持
  1. <!--配置shiro bean生命周期处理器-->
  2. <bean id="lifecycleBeanPostProcessor"
  3. class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
  4. <!--配置自动创建代理-->
  5. <bean
  6. class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
  7. <property name="proxyTargetClass" value="true" />
  8. </bean>
  9. <!-- 开启shiro注解的支持 -->
  10. <bean
  11. class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
  12. <property name="securityManager" ref="securityManager" />
  13. </bean>
4. 在主页访问两个超链接出现异常,提示操作没有对应的角
报错信息如下:
org.springframework.web.util.NestedServletException: Request processing
failed; nested exception is org.apache.shiro.authz.UnauthorizedException:
Subject does not have role [admin]
5. 模拟进行角色认证,在自定义的 Realm 类的授权方法中, 手动给用户添加角色(后期使用数据库查询是否有角色), 然后查看能否正常访问。
  1. @Component
  2. public class MyRealm extends AuthorizingRealm {
  3. @Autowired
  4. UserService userService;
  5. @Override
  6. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection
  7. principalCollection) {
  8. System.out.println("授权方法被执行==============");
  9. //创建角色和权限对象
  10. SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
  11. //模拟添加角色
  12. authorizationInfo.addRole("user");
  13. //返回权限
  14. return authorizationInfo;
  15. }
  16. ...

第七章 shiro权限授权认证

1. 在用户管理设计用户增删改查操作,分别模拟权限验证
  1. <body>
  2. <ul>
  3. <li><a href="/user/add">添加用户</a></li>
  4. <li><a href="/user/delete">删除用户</a></li>
  5. <li><a href="/user/find">查看用户</a></li>
  6. <li><a href="/user/revise">修改用户</a></li>
  7. </ul>
  8. </body>
2.shiro 配置参考如上
3. 在控制器中使用 @RequiresPermissions("permission") 注解来开启请求 的角色验证
  1. @RequiresPermissions("user:add")
  2. @RequestMapping("/user/add")
  3. @ResponseBody
  4. public String add(){
  5. System.out.println("用户添加操作");
  6. return "action user add...";
  7. }
  8. @RequiresPermissions("user:add")
  9. @RequestMapping("/user/delete")
  10. @ResponseBody
  11. public String delete(){
  12. System.out.println("用户删除操作");
  13. return "action user delete...";
  14. }
  15. @RequiresPermissions("user:find")
  16. @RequestMapping("/user/find")
  17. @ResponseBody
  18. public String find(){
  19. System.out.println("用户查看操作");
  20. return "action user find...";
  21. }
  22. @RequiresPermissions("user:revise")
  23. @RequestMapping("/user/revise")
  24. @ResponseBody
  25. public String revise(){
  26. System.out.println("用户修改操作");
  27. return "action user revise...";
  28. }
4. 在自定义的 Realm 类的授权方法中,手动给用户添加权限 (后期使用数据库查询是否有权限),然后查看能否正常访 问。
  1. package com.chen.shior;
  2. import com.chen.bean.User;
  3. import com.chen.service.UserService;
  4. import org.apache.shiro.authc.AuthenticationException;
  5. import org.apache.shiro.authc.AuthenticationInfo;
  6. import org.apache.shiro.authc.AuthenticationToken;
  7. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  8. import org.apache.shiro.authz.AuthorizationInfo;
  9. import org.apache.shiro.authz.SimpleAuthorizationInfo;
  10. import org.apache.shiro.realm.AuthorizingRealm;
  11. import org.apache.shiro.subject.PrincipalCollection;
  12. import org.apache.shiro.util.ByteSource;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.stereotype.Component;
  15. /**
  16. * 自定义Realm,通过mybatis查询教据库密码和盐值,让shiro进行身份验证
  17. */
  18. @Component
  19. public class MyShiroRealm extends AuthorizingRealm {
  20. @Autowired
  21. UserService userService;
  22. //shiro 进行授权操作
  23. @Override
  24. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
  25. System.out.println("授权方法被执行==============");
  26. //1.创建角色和权限对象
  27. SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
  28. //2.1 获取用户登录
  29. String uname = principalCollection.getPrimaryPrincipal().toString();
  30. System.out.println("当前登录用户为:"+uname);
  31. if (uname.equals("admin")){
  32. //正常查询用户的角色(数据库使用set) 现在模拟赋予角色
  33. String role ="admin";
  34. authorizationInfo.addRole(role);
  35. authorizationInfo.addRole("user");
  36. //授予权限正常查询用户的权限,现在模拟赋予权限
  37. authorizationInfo.addStringPermission("user:add");
  38. authorizationInfo.addStringPermission("user:delete");
  39. authorizationInfo.addStringPermission("user:find");
  40. authorizationInfo.addStringPermission("user:revise");
  41. }else {
  42. authorizationInfo.addRole("user");
  43. authorizationInfo.addStringPermission("user:add");
  44. authorizationInfo.addStringPermission("user:find");
  45. }
  46. //返回权限
  47. return authorizationInfo;
  48. }
  49. }
  50. .......
5. 测试看能否访问用户管理页面
配置了 add 权限,点击用户添加可以正常访问;
点击用户删除则抛出异常如下:
org.springframework.web.util.NestedServletException: Request processing
failed; nested exception is org.apache.shiro.authz.UnauthorizedException:
Subject does not have permission [user:delete]
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/636190
推荐阅读
相关标签
  

闽ICP备14008679号