SpringBoot+Mybatis+Mybatis Plus+Shiro实现一个简单的项目架构

本节来使用SpringBoot+Mybatis+Mybatis Plus+Shiro实现简单的项目架构,主要实现的是使用Shiro进行登录验证和权限的验证,以下是实现的全过程,如果有不明白的地方可以下载代码示例:https://download.csdn.net/download/feritylamb/11490995

1、搭建一个SpringBoot项目,参考文章https://blog.csdn.net/feritylamb/article/details/98673201

2、在项目中集成Mybatis,参考文章https://blog.csdn.net/feritylamb/article/details/95771197

3、使用Mybatis Plus生成项目中使用的类,参考文章https://blog.csdn.net/feritylamb/article/details/97616980

4、完成以上几步以后就可以实现shiro的代码了,在pox.xml文件中添加项目所需要的依赖

  1. <project xmlns="http://maven.apache.org/POM/4.0.0"
  2.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.     <modelVersion>4.0.0</modelVersion>
  5.     <groupId>com.gpsbd</groupId>
  6.     <artifactId>hsgpsdw</artifactId>
  7.     <version>0.0.1-SNAPSHOT</version>
  8.     <parent>
  9.         <groupId>org.springframework.boot</groupId>
  10.         <artifactId>spring-boot-starter-parent</artifactId>
  11.         <version>1.5.7.RELEASE</version>
  12.     </parent>
  13.     <properties>
  14.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  15.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  16.         <java.version>1.8</java.version>
  17.     </properties>
  18.     <dependencies>
  19.         <!-- springBoot依赖 -->
  20.         <dependency>
  21.             <groupId>org.springframework.boot</groupId>
  22.             <artifactId>spring-boot-starter-web</artifactId>
  23.         </dependency>
  24.         <!-- mysql依赖 -->
  25.         <dependency>
  26.             <groupId>mysql</groupId>
  27.             <artifactId>mysql-connector-java</artifactId>
  28.             <scope>runtime</scope>
  29.         </dependency>
  30.         <!-- fastjson -->
  31.         <dependency>
  32.             <groupId>com.alibaba</groupId>
  33.             <artifactId>fastjson</artifactId>
  34.             <version>1.2.15</version>
  35.         </dependency>
  36.         <!-- mybatisplus依赖 -->
  37.         <dependency>
  38.             <groupId>com.baomidou</groupId>
  39.             <artifactId>mybatis-plus-boot-starter</artifactId>
  40.             <version>2.2.0</version>
  41.         </dependency>
  42.         <!-- freemarker -->
  43.         <dependency>
  44.             <groupId>org.freemarker</groupId>
  45.             <artifactId>freemarker</artifactId>
  46.         </dependency>
  47.         <!-- Shiro依赖 -->
  48.         <dependency>
  49.             <groupId>org.apache.shiro</groupId>
  50.             <artifactId>shiro-spring</artifactId>
  51.             <version>1.3.2</version>
  52.         </dependency>
  53.     </dependencies>
  54. </project>

5、创建MyRealm文件实现登录验证和角色权限验证,代码如下

  1. package com.gpssoft.config.shiro;
  2. import java.util.ArrayList;
  3. import java.util.List;
  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.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.context.annotation.Lazy;
  14. import com.gpssoft.model.Permissions;
  15. import com.gpssoft.model.vo.UserVo;
  16. import com.gpssoft.service.PermissionsService;
  17. import com.gpssoft.service.UsersService;
  18. public class MyRealm extends AuthorizingRealm {
  19.     @Autowired
  20.     private UsersService usersService;
  21.     @Autowired
  22.     private PermissionsService permissionsService;
  23.     @Override
  24.     public boolean supports(AuthenticationToken token) {
  25.         return token instanceof MyToken;
  26.     }
  27.     /*
  28.      * 只有当需要检测用户权限的时候才会调用此方法,例如checkRole,checkPermission之类的
  29.      */
  30.     @Override
  31.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  32.         // 根据用户名查找角色,请根据需求实现
  33.         UserVo user = (UserVo) principals.getPrimaryPrincipal();
  34.         SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
  35.         // 根据token获取用户的角色和权限
  36.         String[] roleIds = user.getRoleIds().split(",");
  37.         List<Permissions> permissions = new ArrayList<Permissions>();
  38.         for (String roleId : roleIds) {
  39.             permissions.addAll(permissionsService.getPermissionsByRoleId(Integer.parseInt(roleId)));
  40.         }
  41.         String[] roles = user.getRoleKeys().split(",");
  42.         for (String role : roles) {
  43.             authorizationInfo.addRole(role);
  44.         }
  45.         for (Permissions permis : permissions) {
  46.             if (permis.getPermis() != null && !permis.getPermis().equals("")) {
  47.                 authorizationInfo.addStringPermission(permis.getPermis());
  48.             }
  49.         }
  50.         return authorizationInfo;
  51.     }
  52.     /*
  53.      * 默认使用此方法进行用户名正确与否验证,错误抛出异常即可。
  54.      */
  55.     @Override
  56.     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
  57.         String token = (String) auth.getCredentials();
  58.         if (token == null) {
  59.             throw new AuthenticationException("token invalid");
  60.         }
  61.         UserVo user = usersService.getUserByToken(token);
  62.         if (user == null) {
  63.             throw new AuthenticationException(); // 如果密码错误
  64.         }
  65.         // 然后进行客户端消息摘要和服务器端消息摘要的匹配
  66.         return new SimpleAuthenticationInfo(user, token, getName());
  67.     }
  68. }

6、创建ShiroConfig文件,代码如下

  1. package com.gpssoft.config.shiro;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import javax.servlet.Filter;
  5. import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
  6. import org.apache.shiro.mgt.DefaultSubjectDAO;
  7. import org.apache.shiro.spring.LifecycleBeanPostProcessor;
  8. import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
  9. import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
  10. import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
  11. import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
  12. import org.springframework.context.annotation.Bean;
  13. import org.springframework.context.annotation.Configuration;
  14. @Configuration
  15. public class ShiroConfig {
  16.     @Bean
  17.     public ShiroFilterFactoryBean factory(DefaultWebSecurityManager securityManager) {
  18.         ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
  19.         
  20.         Map<String, Filter> filterMap = new HashMap<String, Filter>();
  21.         filterMap.put("myfilter", new MyFilter());
  22.         factoryBean.setFilters(filterMap);
  23.         
  24.         factoryBean.setSecurityManager(securityManager);
  25.         Map<String, String> filterRuleMap = new HashMap<String, String>();
  26. //        filterRuleMap.put("/users/getUser", "anon");
  27.         // 过滤应用接口
  28.         filterRuleMap.put("/**", "myfilter");
  29.         factoryBean.setFilterChainDefinitionMap(filterRuleMap);
  30.         return factoryBean;
  31.     }
  32.     @Bean(name = "securityManager")
  33.     public DefaultWebSecurityManager securityManager() {
  34.         DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
  35.         manager.setRealm(myAuthRealm());
  36.         return manager;
  37.     }
  38.     @Bean(name = "myRealm")
  39.     public MyRealm myAuthRealm() {
  40.         MyRealm myRealm = new MyRealm();
  41.         return myRealm;
  42.     }
  43.     @Bean
  44.     public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
  45.         DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
  46.         advisorAutoProxyCreator.setProxyTargetClass(true);
  47.         return advisorAutoProxyCreator;
  48.     }
  49.     /**
  50.      * 开启aop注解支持
  51.      * @param securityManager
  52.      * @return
  53.      */
  54.     @Bean
  55.     public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) {
  56.         AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
  57.         authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
  58.         return authorizationAttributeSourceAdvisor;
  59.     }
  60. }
     

7、创建所需要的Filter文件类

  1. package com.gpssoft.config.shiro;
  2. import java.io.PrintWriter;
  3. import javax.servlet.ServletRequest;
  4. import javax.servlet.ServletResponse;
  5. import javax.servlet.http.HttpServletRequest;
  6. import org.apache.shiro.SecurityUtils;
  7. import org.apache.shiro.authc.UsernamePasswordToken;
  8. import org.apache.shiro.subject.Subject;
  9. import org.apache.shiro.web.filter.AccessControlFilter;
  10. import com.alibaba.fastjson.JSON;
  11. import com.alibaba.fastjson.JSONObject;
  12. import com.gpssoft.common.ErrorEnum;
  13. import com.gpssoft.model.Result;
  14. public class MyFilter extends AccessControlFilter {
  15.     @Override
  16.     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)throws Exception {
  17.         return false;
  18.     }
  19.     @Override
  20.     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
  21.         HttpServletRequest httpServletRequest = (HttpServletRequest) request;
  22.         String authorization = httpServletRequest.getHeader("token");
  23.         System.out.println("token验证"+authorization);
  24.         if (authorization!=null) {
  25.             try {
  26.                 MyToken token = new MyToken(authorization);
  27.                 // 提交给realm进行登入,如果错误他会抛出异常并被捕获
  28.                 getSubject(request, response).login(token);
  29.                 return true;
  30.             } catch (Exception e) {
  31.                 response401(request, response);
  32.                 return false;
  33.             }
  34.         } else {
  35.             response401(request, response);
  36.             return false;
  37.         }
  38.     }
  39.     
  40.     private void response401(ServletRequest req, ServletResponse resp) throws Exception {
  41.         //HttpServletResponse httpServletResponse = (HttpServletResponse) resp;
  42.         PrintWriter out = null;
  43.         //JSONObject jsonObject = new JSONObject();
  44.         Result result = new Result();
  45.         result.setMsg(ErrorEnum.E_401.getErrorMsg());
  46.         result.setCode(ErrorEnum.E_401.getErrorCode());
  47.         resp.setCharacterEncoding("UTF-8");
  48.         resp.setContentType("application/json");
  49.         out = resp.getWriter();
  50.         out.println(JSON.toJSON(result));
  51.     }
  52. }

以下是Shiro权限管理的讲解:

一、概念

Shiro是一个安全框架,可以进行角色、权限管理。

Shiro主要功能如下:
Authentication(认证):用户身份识别,通常被称为用户“登录”
Authorization(授权):访问控制。比如某个用户是否具有某个操作的使用权限。
Session Management(会话管理):特定于用户的会话管理,甚至在非web 或 EJB 应用程序。
Cryptography(加密):在对数据源使用加密算法加密的同时,保证易于使用。

二、主要的类

1.Subject:当前用户,Subject可以是一个人,也可以是第三方服务
2.SecurityManager:管理所有Subject,可以配合内部安全组件。

3.principals:身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。一个主体可以有多个principals,但只有一个Primary principals,一般是用户名/密码/手机号。
4.credentials:证明/凭证,即只有主体知道的安全值,如密码/数字证书等。
最常见的principals和credentials组合就是用户名/密码了。

5.Realms:用于进行权限信息的验证,需要自己实现。
6.Realm 本质上是一个特定的安全 DAO:它封装与数据源连接的细节,得到Shiro 所需的相关的数据。
在配置 Shiro 的时候,你必须指定至少一个Realm 来实现认证(authentication)和/或授权(authorization)。
我们需要实现Realms的Authentication 和 Authorization。其中 Authentication 是用来验证用户身份,Authorization 是授权访问控制,用于对用户进行的操作授权,证明该用户是否允许进行当前操作,如访问某个链接,某个资源文件等。

7.SimpleHash,可以通过特定算法(比如md5)配合盐值salt,对密码进行多次加密。

 三、Shiro配置

1.Spring集成Shiro一般通过xml配置,SpringBoot集成Shiro一般通过java代码配合@Configuration和@Bean配置。

2.Shiro的核心通过过滤器Filter实现。Shiro中的Filter是通过URL规则来进行过滤和权限校验,所以我们需要定义一系列关于URL的规则和访问权限。

3.SpringBoot集成Shiro,我们需要写的主要是两个类,ShiroConfiguration类,还有继承了AuthorizingRealm的Realm类

ShiroConfiguration类,用来配置Shiro,注入各种Bean。

包括过滤器(shiroFilter)、安全事务管理器(SecurityManager)、密码凭证(CredentialsMatcher)、aop注解支持(authorizationAttributeSourceAdvisor)等等

Realm类,包括登陆认证(doGetAuthenticationInfo)、授权认证(doGetAuthorizationInfo)

四、权限拦截 Filter

当运行一个Web应用程序时,Shiro将会创建一些有用的默认 Filter 实例,并自动地将它们置为可用,而这些默认的 Filter 实例是被 DefaultFilter 枚举类定义的,当然我们也可以自定义 Filter 实例

配置缩写对应的过滤器功能
anonAnonymousFilter指定url可以匿名访问
authcFormAuthenticationFilter指定url需要form表单登录,默认会从请求中获取usernamepassword,rememberMe等参数并尝试登录,如果登录不了就会跳转到loginUrl配置的路径。我们也可以用这个过滤器做默认的登录逻辑,但是一般都是我们自己在控制器写登录逻辑的,自己写的话出错返回的信息都可以定制嘛。
authcBasicBasicHttpAuthenticationFilter指定url需要basic登录
logoutLogoutFilter登出过滤器,配置指定url就可以实现退出功能,非常方便
noSessionCreationNoSessionCreationFilter禁止创建会话
permsPermissionsAuthorizationFilter需要指定权限才能访问
portPortFilter需要指定端口才能访问
restHttpMethodPermissionFilter将http请求方法转化成相应的动词来构造一个权限字符串,这个感觉意义不大,有兴趣自己看源码的注释
rolesRolesAuthorizationFilter需要指定角色才能访问
sslSslFilter需要https请求才能访问
userUserFilter需要已登录或“记住我”的用户才能访问

至此,这篇文章就结束了,欢迎大家交流学习。

代码示例:https://download.csdn.net/download/feritylamb/11490995

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值