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.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3.     4.0.0
  4.     com.gpsbd
  5.     hsgpsdw
  6.     0.0.1-SNAPSHOT
  7.     
  8.         org.springframework.boot
  9.         spring-boot-starter-parent
  10.         1.5.7.RELEASE
  11.     
  12.     
  13.         UTF-8
  14.         UTF-8
  15.         1.8
  16.     
  17.     
  18.         
  19.         
  20.             org.springframework.boot
  21.             spring-boot-starter-web
  22.         
  23.         
  24.         
  25.             mysql
  26.             mysql-connector-java
  27.             runtime
  28.         
  29.         
  30.         
  31.             com.alibaba
  32.             fastjson
  33.             1.2.15
  34.         
  35.         
  36.         
  37.             com.baomidou
  38.             mybatis-plus-boot-starter
  39.             2.2.0
  40.         
  41.         
  42.         
  43.             org.freemarker
  44.             freemarker
  45.         
  46.         
  47.         
  48.             org.apache.shiro
  49.             shiro-spring
  50.             1.3.2
  51.         
  52.     

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 = new ArrayList();
  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 filterMap = new HashMap();
  21.         filterMap.put("myfilter", new MyFilter());
  22.         factoryBean.setFilters(filterMap);
  23.         
  24.         factoryBean.setSecurityManager(securityManager);
  25.         Map filterRuleMap = new HashMap();
  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 实例

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

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

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

 

 

你可能感兴趣的:(Java中SpringBoot)