• shiro


    1.功能:

    • 身份认证(核心)
    • 资源授权(核心)
    • 记住我
    • session 管理
    • 加密

    2.组件

    • subject:应用层代码和shrio代码的中间组件。
    • 核心功能放在realm
    • realm注册到securityManager管理
    • shiroFilterFactoryBean,访问策略,不同的url,不同的访问策略
    • 方言管理器组件
    • 实现注解的组件
    • session管理器组件
    • 记住我组件

    3.流程

    一、身份认证流程

    •    页面输入用户名和密码 ---
      • 跳转到登录控制器----
      • 调用service---
      • 得到subject----
      • 封装一个令牌------
      • 装载用户名和密码----
      • subject.login(令牌) ----
      • realm的身份认证方法
      • 取用户名,通过用户名查找数据库的user信息----
      • 查到了封装一个身份验证1器----
      • 用身份验证器和令牌比对----
      • 成功则登录成功授权。

    二、资源授权流程

    • 页面输入用户名和密码
    • 登录控制器
    • 调用service
    • 得到subject
    • 通过subject取调用subject.checkRoles()找到身份
    • 等待登录成功,成功后,进行页面跳转,或者页面访问,放入封装信息
    • 遇到页面shrio标签或者注解
    • realm资源授权方法,从认证中获取封装的信息,
    • 从数据库查询当前用户的角色列表
    • 在去数据库查询每个角色拥有的资源列表
    • 将角色列表和资源列表封装到资源授权器
    • 再去用资源授权器去和页面的标签或者注解比对,有权限则访问成功,反之,抛出异常

    三、实现

     1.servlet实现(不讲)

     2.spring boot 实现

    1.引入相应的依赖,pom

    1. <dependency>
    2. <groupId>org.apache.shirogroupId>
    3. <artifactId>shiro-spring-boot-web-starterartifactId>
    4. <version>1.4.1version>
    5. dependency>
    6. <dependency>
    7. <groupId>com.github.theborakompanionigroupId>
    8. <artifactId>thymeleaf-extras-shiroartifactId>
    9. <version>2.0.0version>
    10. dependency>

    2.配置

    1.application.properties

    1. #开启shiro
    2. shiro.web.enabled=true

    3.shrio组件

    1.编写Realm配置类

    1. /**
    2. * MyRealm:资源授权和身份验证
    3. */
    4. @Component
    5. public class MyRealm extends AuthorizingRealm {
    6. //1.将MyRealm注册为bean,因为要调用service
    7. @Autowired
    8. private UserService userService;
    9. @Autowired
    10. private RoleService roleService;
    11. @Autowired
    12. private ResourceService resourceService;
    13. //资源授权
    14. @Override
    15. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
    16. //资源授权器
    17. SimpleAuthorizationInfo authorization = new SimpleAuthorizationInfo();
    18. //1.realm资源授权方法,从认证中获取封装的信息,
    19. User user = (User) principal.getPrimaryPrincipal();
    20. //2. 从数据库查询当前用户的角色列表,并转载到资源授权器里
    21. List roles = roleService.getRolesByUserId(user.getId());
    22. //把当前用户的角色列表加入进资源授权器
    23. roles.stream().forEach(item ->{
    24. authorization.addRole(item.getRoleName());
    25. //3.在去数据库查询每个角色拥有的资源列表,并转载到资源授权器里
    26. List resources = (List) resourceService.getResourceById(item.getId());
    27. //4.将角色列表和资源列表封装到资源授权器
    28. resources.stream().forEach(item2 ->{
    29. authorization.addStringPermission(item2.getPermission());
    30. });
    31. });
    32. return authorization;
    33. }
    34. //身份验证
    35. @Override
    36. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    37. //1.获取用户名
    38. String userName = (String) token.getPrincipal();
    39. //2.通过用户名查找数据库的user信息,调用service
    40. User user = userService.getUserByUserName(userName);
    41. if (null == user){
    42. throw new UnknownAccountException("User name is not exit.");
    43. }
    44. //3.封装身份验证器,new SimpleAuthenticationInfo(Object principal, Object credentials, String realmName);
    45. return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
    46. }
    47. }

    2.编写配置shrio组件类:config/shrio/ShiroConfig

    • 组件安全管理器: securityManager
    • shiro 过滤器工厂, ShiroFilterFactoryBean,需要注入安全管理器
    • -配置 shiro 过滤器工厂:ShiroFilterFactoryBean

    • -----------------
    • -拦截权限
      • anon:匿名访问,无需登录 ---- AnonymousFilter
      • authc:登录后才能访问 ---- FormAuthenticationFilter
      • user:登录过能访问 ---- UserFilter
      • logout:登出 ---- LogoutFilter

    • ------------------
    • URL匹配风格
      • ?:匹配一个字符,如 /admin? 将匹配 /admin1,但不匹配 /admin 或 /admin/
      • *:匹配零个或多个字符串,如 /admin* 将匹配 /admin 或/admin123,但不匹配 /admin/1
      • **:匹配路径中的零个或多个路径,如 /admin/** 将匹配 /admin/a 或 /admin/a/b

    • -----------------------
      • -方法名不能乱写,如果我们定义为别的名称,又没有添加注册过滤器的配置,
      • -那么 shiro 会加载 ShiroWebFilterConfiguration 过滤器,
      • -该过滤器会寻找 shiroFilterFactoryBean,找不到会抛出异常
    • 注册shiro方言,让 thymeleaf 支持 shiro 标签
    • DefaultAdvisorAutoProxyCreator, Advisor 代理类生成器
    • 创建 AuthorizationAttributeSourceAdvisor,扫描 Shiro 注解
    • 代码
    1. @Configuration
    2. public class ShrioConfig {
    3. @Autowired
    4. private MyRealm myRealm;
    5. //组件安全管理器: securityManager
    6. @Bean
    7. public SecurityManager securityManager(){
    8. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    9. securityManager.setRealm(myRealm);
    10. return securityManager;
    11. }
    12. /**
    13. * -配置 shiro 过滤器工厂:ShiroFilterFactoryBean
    14. * -----------------
    15. * -拦截权限
    16. * anon:匿名访问,无需登录 ---- AnonymousFilter
    17. * authc:登录后才能访问 ---- FormAuthenticationFilter
    18. * user:登录过能访问 ---- UserFilter
    19. * logout:登出 ---- LogoutFilter
    20. * ------------------
    21. * URL匹配风格
    22. * ?:匹配一个字符,如 /admin? 将匹配 /admin1,但不匹配 /admin 或 /admin/
    23. * *:匹配零个或多个字符串,如 /admin* 将匹配 /admin 或/admin123,但不匹配 /admin/1
    24. * **:匹配路径中的零个或多个路径,如 /admin/** 将匹配 /admin/a 或 /admin/a/b
    25. * -----------------------
    26. * -方法名不能乱写,如果我们定义为别的名称,又没有添加注册过滤器的配置,
    27. * -那么 shiro 会加载 ShiroWebFilterConfiguration 过滤器,
    28. * -该过滤器会寻找 shiroFilterFactoryBean,找不到会抛出异常
    29. */
    30. //组件:shiro 过滤器工厂, ShiroFilterFactoryBean,需要注入安全管理器
    31. @Bean
    32. public ShiroFilterFactoryBean shiroFilterFactoryBean(){
    33. ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
    34. //1.注入安全管理器
    35. filterFactory.setSecurityManager(securityManager());
    36. //2.设置登录页面和登录成功页面
    37. filterFactory.setLoginUrl("/login");
    38. filterFactory.setSuccessUrl("/test/thymeleafTest");
    39. //3.设置其余地址的访问规则,放在map中,key:通配符,value:访问策略
    40. /**
    41. * anon:匿名访问,无需登录 ---- AnonymousFilter
    42. * authc:登录后才能访问 ---- FormAuthenticationFilte
    43. * user:登录过能访问 ---- UserFilter
    44. * logout:登出 ---- LogoutFilter
    45. */
    46. Map filterMap = new LinkedHashMap<>();
    47. //匿名策略:全部开放 anon:
    48. // 登录注册
    49. filterMap.put("/login","anon");
    50. filterMap.put("/register","anon");
    51. // 静态资源
    52. filterMap.put("/favicon.ico","anon");
    53. filterMap.put("/css/**","anon");
    54. filterMap.put("/images/**","anon");
    55. filterMap.put("/js/**","anon");
    56. filterMap.put("/vendors/**","anon");
    57. filterMap.put("/static/**","anon");
    58. // 测试模块
    59. filterMap.put("/test/**","anon");
    60. // api开发
    61. filterMap.put("/api/**","anon");
    62. //非匿名策略
    63. filterMap.put("/**","authc");
    64. //4.返回过滤器工厂
    65. filterFactory.setFilterChainDefinitionMap(filterMap);
    66. return filterFactory;
    67. }
    68. /**
    69. * - 注册shiro方言,让 thymeleaf 支持 shiro 标签
    70. */
    71. @Bean
    72. public ShiroDialect shiroDialect(){
    73. return new ShiroDialect();
    74. }
    75. /**
    76. * DefaultAdvisorAutoProxyCreator, Advisor 代理类生成器
    77. */
    78. @Bean
    79. @DependsOn({"lifecycleBeanPostProcessor"})
    80. public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
    81. DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    82. advisorAutoProxyCreator.setProxyTargetClass(true);
    83. return advisorAutoProxyCreator;
    84. }
    85. /**
    86. * - 创建 AuthorizationAttributeSourceAdvisor,扫描 Shiro 注解
    87. */
    88. @Bean
    89. public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
    90. AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    91. authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
    92. return authorizationAttributeSourceAdvisor;
    93. }
    94. }

    4.实现

    1.身份认证实现

    1. @Override
    2. @Transactional
    3. public Result login(User user) {
    4. //1. 得到subject----
    5. Subject subject = SecurityUtils.getSubject();
    6. //2. 封装一个令牌,装载用户名和密码------
    7. UsernamePasswordToken token = new UsernamePasswordToken(
    8. user.getUserName(),
    9. MD5Util.getMD5(user.getPassword()));
    10. //3. subject.login(令牌)----
    11. try {
    12. //令牌,身份认证和资源授权
    13. subject.login(token);
    14. subject.checkRole();
    15. //获取当前用户,并设置到session中
    16. //获取MyRealm认证返回的user
    17. User temp = (User) subject.getPrincipal();
    18. //返回apache的session
    19. Session session = subject.getSession();
    20. session.setAttribute("user",temp);
    21. return new Result<>(Result.ResultStatus.SUCCESS.code,"SUCCESS",temp);
    22. } catch (Exception e) {
    23. e.printStackTrace();
    24. LOGGER.debug(e.getMessage());
    25. return new Result<>(Result.ResultStatus.FAILD.code,e.getMessage());
    26. }
    27. }

    2.资源授权

    • 整套系统的权限规则
    • admin ----最高权限
    • manager --------除了删除之外都能干
    • staff ---------查看共性信息,访问测试模块、修改自己的信息

    • 为多用户分配角色,资源细腻
    • admin账户---admin角色 ----拥有删除资源
    • manager账户 ----mannager角色 -----没有删除功能
    • staff账户 ------staff角色 -----查看共性信息,访问测试模块、修改自己的信息

  • 相关阅读:
    MySQL表的增删改查
    Python使用pillow库往图片上写入文字或覆盖另一张图片
    Linux网络编程TCP-UDP套接字
    pid,ppid,pgid,sid进程间关系
    Build a Large Language Model (From Scratch) 从头开始构建大型语言模型(第二章)学习笔记(上)
    西门子S7-1200F或1500F系列安全PLC的组态步骤和基础编程(一)
    (附源码)计算机毕业设计SSM酒店客户管理系统
    【数学篇】08 # 如何利用三角剖分和向量操作描述并处理多边形?
    自动化运维工具Ansible
    Elasticsearch - DSL 查询语句
  • 原文地址:https://blog.csdn.net/weixin_46048259/article/details/126651439