1、SpringBoot整合Shiro

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。

1.1、shiro简介

shiro有个核心组件,分别为SubjectSecurityManagerRealms

  • Subject:相当于当前操作的”用户“,这个用户不一定是一个具体的人,是一个抽象的概念,表明的是和当前程序进行交互的任何东西,例如爬虫、脚本、等等。所有的Subject都绑定到SecurityManager上,与 Subject 的所有交互都会委托给 SecurityManager;可以把 Subject 认为是一个门面;SecurityManager 才是实际的执行者。
  • SecurityManager:这个是shiro框架的核心,所有与安全相关的操作都会与它进行交互,它管理者所有的Subject。
  • Realms:充当了Shiro与应用安全数据间的”桥梁“,当对用户执行认证(登录)和授权(访问控制)验证时,SecurityManager 需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作。

如果想要更加深入的了解的shrio可以参考:https://www.w3cschool.cn/shiro/co4m1if2.html

1.2、代码的具体实现

1.2.1、Maven的配置

  1. <!--shiro-->
  2. <dependency>
  3. <groupId>org.apache.shiro</groupId>
  4. <artifactId>shiro-spring-boot-starter</artifactId>
  5. <version>1.7.1</version>
  6. </dependency>
  7. <!--shiro整合thymeleaf-->
  8. <dependency>
  9. <groupId>com.github.theborakompanioni</groupId>
  10. <artifactId>thymeleaf-extras-shiro</artifactId>
  11. <version>2.0.0</version>
  12. </dependency>
  13. <!--shiro缓存-->
  14. <dependency>
  15. <groupId>org.apache.shiro</groupId>
  16. <artifactId>shiro-ehcache</artifactId>
  17. <version>1.7.1</version>
  18. </dependency>

shiro默认是与jsp进行使用的,而这里是shiro整合thymeleaf所有要导入shiro整合thymeleaf的jar包

1.2.2、整合需要实现的类

一般来说整合只需要完成两个类的实现即可

一个是 ShiroConfig 一个是 CustomerRealm

如果需要添加shiro缓存并且不是自带的缓存而是redis缓存还需要进行另外两个类的编写

一个是 RedisCache 一个是 RedisCacheManager

1.2.3、项目结构

1.2.4、ShiroConfig的实现

未加shiro的缓存

  1. package com.yuwen.config;
  2. import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
  3. import com.yuwen.shiro.cache.RedisCacheManager;
  4. import com.yuwen.shiro.realm.CustomerRealm;
  5. import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
  6. import org.apache.shiro.realm.Realm;
  7. import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
  8. import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
  9. import org.springframework.beans.factory.annotation.Qualifier;
  10. import org.springframework.context.annotation.Bean;
  11. import org.springframework.context.annotation.Configuration;
  12. import java.util.HashMap;
  13. import java.util.Map;
  14. @Configuration
  15. public class ShiroConfig {
  16. //让页面shiro标签生效
  17. @Bean
  18. public ShiroDialect shiroDialect(){
  19. return new ShiroDialect();
  20. }
  21. //1、创建shiroFilter 负责拦截所有请求
  22. @Bean
  23. public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
  24. ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
  25. //给filter设置安全管理
  26. factoryBean.setSecurityManager(defaultWebSecurityManager);
  27. //配置系统的受限资源
  28. //配置系统公共资源 全部都能访问的设置anon
  29. Map<String,String> map = new HashMap<>();
  30. map.put("/main","authc");//请求这个资源需要认证和授权 authc表示需要认证后才能访问
  31. map.put("/admin","roles[admin]"); //表示admin角色才能访问 roles[]表示需要什么角色才能访问
  32. map.put("/manage","perms[user:*:*]"); //表示需要user:*:*权限才能访问 perms[]表示需要什么权限才能访问
  33. //访问需要认证的页面如果未登录会跳转到/login路由进行登陆
  34. factoryBean.setLoginUrl("/login");
  35. //访问未授权页面会自动跳转到/unAuth路由
  36. factoryBean.setUnauthorizedUrl("/unAuth");
  37. factoryBean.setFilterChainDefinitionMap(map);
  38. return factoryBean;
  39. }
  40. //2、创建安全管理器
  41. @Bean
  42. public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("getRealm") Realm realm){
  43. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  44. //给安全管理器设置
  45. securityManager.setRealm(realm);
  46. return securityManager;
  47. }
  48. //3、创建自定义的realm
  49. @Bean
  50. public Realm getRealm(){
  51. CustomerRealm customerRealm = new CustomerRealm();
  52. //修改凭证校验匹配器
  53. HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
  54. //设置加密算法为md5
  55. credentialsMatcher.setHashAlgorithmName("MD5");
  56. //设置散列次数
  57. credentialsMatcher.setHashIterations(1024);
  58. customerRealm.setCredentialsMatcher(credentialsMatcher);
  59. return customerRealm;
  60. }
  61. }

因为一般在数据库中设置明文密码不安全,所有我这里对密码进行了md5加密,我的加密方式为:密码 = 密码+盐+散列次数 而后进行MD5加密 所以这里创建自定义的realm时需要进行设置匹配器这样登录时密码才能匹配成功

1.2.5、CustomerRealm的实现

  1. package com.yuwen.shiro.realm;
  2. import com.yuwen.pojo.User;
  3. import com.yuwen.pojo.vo.ViewPerms;
  4. import com.yuwen.pojo.vo.ViewRole;
  5. import com.yuwen.service.UserService;
  6. import com.yuwen.shiro.salt.MyByteSource;
  7. import org.apache.shiro.authc.AuthenticationException;
  8. import org.apache.shiro.authc.AuthenticationInfo;
  9. import org.apache.shiro.authc.AuthenticationToken;
  10. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  11. import org.apache.shiro.authz.AuthorizationInfo;
  12. import org.apache.shiro.authz.SimpleAuthorizationInfo;
  13. import org.apache.shiro.realm.AuthorizingRealm;
  14. import org.apache.shiro.subject.PrincipalCollection;
  15. import org.apache.shiro.util.CollectionUtils;
  16. import org.springframework.util.ObjectUtils;
  17. import javax.annotation.Resource;
  18. import java.util.List;
  19. //自定义realm
  20. public class CustomerRealm extends AuthorizingRealm {
  21. @Resource
  22. private UserService userService;
  23. //授权
  24. @Override
  25. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
  26. //获取身份信息
  27. String primaryPrincipal = (String)principalCollection.getPrimaryPrincipal();
  28. //根据主身份信息获取角色 和 权限信息
  29. List<ViewRole> roles = userService.findRolesByUsername(primaryPrincipal);
  30. if (!CollectionUtils.isEmpty(roles)){
  31. SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
  32. roles.forEach(viewRole -> {
  33. simpleAuthorizationInfo.addRole(viewRole.getName());
  34. //权限信息
  35. List<ViewPerms> perms = userService.findPermsByRoleId(viewRole.getName());
  36. if (!CollectionUtils.isEmpty(perms)){
  37. perms.forEach(viewPerms -> {
  38. simpleAuthorizationInfo.addStringPermission(viewPerms.getPName());
  39. });
  40. }
  41. });
  42. return simpleAuthorizationInfo;
  43. }
  44. return null;
  45. }
  46. //认证
  47. @Override
  48. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
  49. //获取登入的身份信息
  50. String principal = (String) authenticationToken.getPrincipal();
  51. User user = userService.findByUsername(principal);
  52. if (!ObjectUtils.isEmpty(user)){
  53. //ByteSource.Util.bytes(user.getSalt()) 通过这个工具将盐传入
  54. //如果身份认证验证成功,返回一个AuthenticationInfo实现;
  55. return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),new MyByteSource(user.getSalt()),this.getName());
  56. }
  57. return null;
  58. }
  59. }

在登录时会自动调用这个身份验证 在验证时如果出错,会报异常,我在controller层接收了异常并处理

controller层中登录时的异常处理

  1. @PostMapping("/login")
  2. public String login(String username,String password){
  3. //获取主体对象
  4. Subject subject = SecurityUtils.getSubject();
  5. try {
  6. //自动调用CustomerRealm 类中的身份验证方法
  7. subject.login(new UsernamePasswordToken(username,password));
  8. return "index";
  9. }catch (UnknownAccountException e){ //接收异常并处理
  10. e.printStackTrace();
  11. model.addAttribute("msg","用户名有误,请重新登录");
  12. }catch (IncorrectCredentialsException e){//接收异常并处理
  13. e.printStackTrace();
  14. model.addAttribute("msg","密码有误,请重新登录");
  15. }
  16. return "login";
  17. }

1.2.6、shiro缓存配置

定义了shiro缓存,用户登录后,其用户信息、拥有的角色 / 权限不必每次去查,这样可以提高效率

默认缓存的配置

ShiroConfig中getRealm() 方法中开启缓存管理

  1. @Bean
  2. public Realm getRealm(){
  3. CustomerRealm customerRealm = new CustomerRealm();
  4. //开启缓存管理
  5. customerRealm.setCacheManager(new EhCacheManager());
  6. //开启全局缓存
  7. customerRealm.setCachingEnabled(true);
  8. //开启认证缓存
  9. customerRealm.setAuthenticationCachingEnabled(true);
  10. customerRealm.setAuthenticationCacheName("authenticationCache");
  11. //开启权限缓存
  12. customerRealm.setAuthorizationCachingEnabled(true);
  13. customerRealm.setAuthorizationCacheName("authorizationCache");
  14. return customerRealm;
  15. }

与reids整合的缓存这里就不说明了,放在源码里自己查看,源码在下方

1.2.7、主页index.html的设置

在这里用标签来判断某些区域需要认证或什么角色或者什么权限才能访问

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
  3. xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>首页</title>
  7. <link rel="shortcut icon" href="#">
  8. </head>
  9. <body>
  10. <h1>index</h1>
  11. <a href="/logout">退出</a>
  12. <div>
  13. <a href="/main">main</a> | <a href="/manage">manage</a> | <a href="/admin">admin</a>
  14. </div>
  15. <!--获取认证信息-->
  16. 用户:<span shiro:principal=""></span><hr>
  17. <!--认证处理-->
  18. <span shiro:authenticated=""><hr>
  19. 显示认证通过内容
  20. </span>
  21. <span shiro:notAuthenticated=""><hr>
  22. 没有认证时 显示
  23. </span>
  24. <!--授权角色-->
  25. <span shiro:hasRole="admin"><hr>
  26. admin角色 显示
  27. </span>
  28. <span shiro:hasPermission="user:*:*"><hr>
  29. 具有用户模块的"user:*:*"权限 显示
  30. </span>
  31. </body>
  32. </html>

1.3、简单测试

1.3.1、admin角色所有权限测试

1.3.2、无角色有权限测试

1.3.3、无角色无权限测试



1.4 项目源码

需要源码的在这:https://gitee.com/residual-temperature/shiro-demo

SpringBoot整合Shiro实现权限控制的更多相关文章

  1. SpringBoot整合Shiro实现权限控制,验证码

    本文介绍 SpringBoot 整合 shiro,相对于 Spring Security 而言,shiro 更加简单,没有那么复杂. 目前我的需求是一个博客系统,有用户和管理员两种角色.一个用户可能有 ...

  2. springboot集成shiro 实现权限控制(转)

    shiro apache shiro 是一个轻量级的身份验证与授权框架,与spring security 相比较,简单易用,灵活性高,springboot本身是提供了对security的支持,毕竟是自 ...

  3. SpringBoot集成Shiro实现权限控制

    Shiro简介 Apache Shiro是一个功能强大且易于使用的Java安全框架,用于执行身份验证,授权,加密和会话管理.使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移 ...

  4. springboot整合shiro进行权限管理

    背景:springboot2.1,shiro1.4:由于目前的小项目没做登录,但是客户又需要加上权限,因此楼主就想到了shiro(这是单独的项目,需要集成后台管理系统) shiro简介 Apache ...

  5. spring-boot整合shiro作权限认证

    spring-shiro属于轻量级权限框架,即使spring-security更新换代,市场上大多数企业还是选择shiro 废话不多说  引入pom文件 <!--shiro集成spring--& ...

  6. shiro系列三、ssm框架整合shiro实现权限控制

    shiro权限框架是一个非常优秀的框架,前面的几篇文章对shiro进行了非常详细的介绍和原理分析,那么接下来让我们开始在web项目中使用它(javase也能用shiro): 一.数据库表结构设计 二. ...

  7. spring-boot整合shiro实现权限管理

    1.运行环境 开发工具:intellij idea JDK版本:1.8 项目管理工具:Maven 4.0.0 2.GITHUB地址 https://github.com/nbfujx/springBo ...

  8. SpringBoot整合Shiro权限框架实战

    什么是ACL和RBAC ACL Access Control list:访问控制列表 优点:简单易用,开发便捷 缺点:用户和权限直接挂钩,导致在授予时的复杂性,比较分散,不便于管理 例子:常见的文件系 ...

  9. SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建

    SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建 技术栈 : SpringBoot + shiro + jpa + freemark ,因为篇幅原因,这里只 ...

随机推荐

  1. ML Pipelines管道

    ML Pipelines管道 In this section, we introduce the concept of ML Pipelines. ML Pipelines provide a uni ...

  2. 快速人体姿态估计:CVPR2019论文阅读

    快速人体姿态估计:CVPR2019论文阅读 Fast Human Pose Estimation 论文链接: http://openaccess.thecvf.com/content_CVPR_201 ...

  3. TVM安装常用问题

    TVM安装常用问题 如何添加新的硬件后端 如果硬件后端支持LLVM,则可以通过设置正确的目标三元组来直接生成代码target. 如果目标硬件是GPU,请尝试使用cuda,opencl或vulkan后端 ...

  4. CUDA统一内存分析

    CUDA统一内存分析 PascalMIG 如 NVIDIA Titan X 和 NVIDIA Tesla P100 是第一个包含页 GPUs 定额引擎的 GPUs ,它是统一内存页错误处理和 MIG ...

  5. CVPR2020:利用图像投票增强点云中的三维目标检测(ImVoteNet)

    CVPR2020:利用图像投票增强点云中的三维目标检测(ImVoteNet) ImVoteNet: Boosting 3D Object Detection in Point Clouds With ...

  6. Python分析离散心率信号(中)

    Python分析离散心率信号(中) 一些理论和背景 心率信号不仅包含有关心脏的信息,还包含有关呼吸,短期血压调节,体温调节和荷尔蒙血压调节(长期)的信息.也(尽管不总是始终如一)与精神努力相关联,这并 ...

  7. XML文件存在中文注释报错问题( 3 字节的 UTF-8 序列的字节 3 无效)

    今天在做mybatis项目的时候,给映射文件添加了中文注释后,程序就报错.把中文注释删除后,程序又可以正常执行.解决方法在下文提到. 我的xml映射文件如下: <?xml version=&qu ...

  8. 谁能干掉了if else

    很多人觉得自己写的是业务代码,按照逻辑写下去,再把公用的方法抽出来复用就可以了,设计模式根本就没必要用,更没必要学. 一开始的时候,我也是这么想,直到我遇到... 举个例子 我们先看一个普通的下单拦截 ...

  9. Visual Studio 2019本地不能运行Azure Functions

    最近一个项目,需要维护同事写得代码,主要是一堆基于 .net core 3.1 的 Azure Functions.想起2年前第一次接触 Azure Functions(那次是基于.net frame ...

  10. Android Gradle插件

    目录 什么是Gradle 编写方法 buildSrc 基础概念 Extension 自定义Task Plugin Transformer Gradle用处 好文章 常见问题 Gradle插件练习地址: ...