SpringBoot集成Shiro进行权限控制和管理的示例

shiro

apache shiro 是一个轻量级的身份验证与授权框架,与spring security 相比较,简单易用,灵活性高,springboot本身是提供了对security的支持,毕竟是自家的东西。springboot暂时没有集成shiro,这得自己配。

1 . 添加依赖

<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-spring</artifactId>
  <version>1.2.5</version>
</dependency>
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-ehcache</artifactId>
  <version>1.2.5</version>
</dependency>

2 . 编写Shiro配置类

package com.xbz.web.system.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
/**
 * shiro配置类
 * ApacheShiro核心通过Filter来实现权限控制和拦截 , 就好像SpringMVC通过DispachServlet来主控制请求分发一样 .
 * 既然是使用Filter , 即是通过URL规则来进行过滤和权限校验 , 所以我们需要定义一系列关于URL的规则和访问权限
 */
@Configuration
public class ShiroConfiguration {
  /**
   * DefaultAdvisorAutoProxyCreator , Spring的一个bean , 由Advisor决定对哪些类的方法进行AOP代理 .
   */
  @Bean
  @ConditionalOnMissingBean
  public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
    defaultAAP.setProxyTargetClass(true);
    return defaultAAP;
  } 

  /**
   * ShiroFilterFactoryBean : 为了生成ShiroFilter , 处理拦截资源文件问题 .
   * 它主要保持了三项数据 , securityManager , filters , filterChainDefinitionManager .
   * 注意 : 单独一个ShiroFilterFactoryBean配置是或报错的 , 因为在初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
   *
   * FilterChain定义说明
   * 1 . 一个URL可以配置多个Filter , 使用逗号分隔
   * 2 . 当设置多个过滤器时 , 全部验证通过 , 才视为通过
   * 3 . 部分过滤器可指定参数 , 如perms , roles
   *
   */
  @Bean
  public ShiroFilterFactoryBean shiroFilterFactoryBean() {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager());
    shiroFilterFactoryBean.setLoginUrl("/login");//不设置默认找web工程根目录下的login.jsp页面
    shiroFilterFactoryBean.setSuccessUrl("/index");//登录成功之后要跳转的连接
    shiroFilterFactoryBean.setUnauthorizedUrl("/403");//未授权跳转页面
    /* //自定义拦截器 , 多个filter的设置 */
//    Map<String, Filter> filters = new LinkedHashMap<>();
//    LogoutFilter logoutFilter = new LogoutFilter();//限制同一帐号同时在线的个数。或单点登录等
//    logoutFilter.setRedirectUrl("/login");
//    filters.put("logout",null);
//    shiroFilterFactoryBean.setFilters(filters);
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
    //filterChainDefinitionManager必须是LinkedHashMap因为它必须保证有序
    filterChainDefinitionMap.put("/css/**", "anon");//静态资源不要求权限 , 若有其他目录下文件(如js,img等)也依此设置
    filterChainDefinitionMap.put("/", "anon");
    filterChainDefinitionMap.put("/login", "anon");//配置不需要权限访问的部分url
    filterChainDefinitionMap.put("/logout", "logout");
    filterChainDefinitionMap.put("/user/**", "authc,roles[ROLE_USER]");//用户为ROLE_USER 角色可以访问 . 由用户角色控制用户行为 .
    filterChainDefinitionMap.put("/events/**", "authc,roles[ROLE_ADMIN]");
    //    filterChainDefinitionMap.put("/user/edit/**", "authc,perms[user:edit]");// 这里为了测试 , 固定写死的值 , 也可以从数据库或其他配置中读取 , 此处是用权限控制 

    filterChainDefinitionMap.put("/**", "authc");//需要登录访问的资源 , 一般将/**放在最下边 

    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
  } 

  //region Cookie及Session
  // ==================== Cookie及Session管理 begin ====================
  private static final String COOKIE_NAME = "rememberMe";
  /** cookie对象管理 */
  public SimpleCookie rememberMeCookie(){
    //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
    SimpleCookie simpleCookie = new SimpleCookie(COOKIE_NAME);
    simpleCookie.setMaxAge(604800);//记住我cookie生效时间7天 ,单位秒
    return simpleCookie;
  } 

  /** cookie管理对象 : 记住我功能 */
  public CookieRememberMeManager rememberMeManager(){
    CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
    cookieRememberMeManager.setCookie(rememberMeCookie());
    cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));//rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
    return cookieRememberMeManager;
  } 

  @Bean
  SessionDAO sessionDAO() {
    return new MemorySessionDAO();
  } 

  @Bean
  public SessionManager sessionManager() {
    DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
    Collection<SessionListener> listeners = new ArrayList<>();
    listeners.add(new BDSessionListener());
    sessionManager.setSessionListeners(listeners);
    sessionManager.setSessionDAO(sessionDAO());
    return sessionManager;
  }
  // ==================== Cookie及Session管理 end ====================
  //endregion 

  /**
   * SecurityManager : 核心安全事务管理器 , 权限管理
   * 这个类组合了登陆 , 登出 , 权限 , session的处理 . 是个比较重要的类 .
   */
  @Bean(name = "securityManager")
  public DefaultWebSecurityManager securityManager() {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(shiroRealm());
    securityManager.setCacheManager(ehCacheManager());////用户授权/认证信息Cache, 采用EhCache 缓存 

    // 自定义session管理 使用redis
    securityManager.setSessionManager(sessionManager()); 

    //注入记住我管理器;
    securityManager.setRememberMeManager(rememberMeManager());
    return securityManager;
  } 

  /**
   * ShiroRealm , 这是个自定义的认证类 , 继承自AuthorizingRealm ,
   * 负责用户的认证和权限的处理 , 可以参考JdbcRealm的实现 .
   */
  @Bean
  @DependsOn("lifecycleBeanPostProcessor")
  public ShiroRealm shiroRealm(CredentialsMatcher matcher) {
    ShiroRealm realm = new ShiroRealm();
    realm.setCredentialsMatcher(matcher);//密码校验实现
    return realm;
  } 

  /**
   * EhCacheManager , 缓存管理
   * 用户登陆成功后 , 把用户信息和权限信息缓存起来 , 然后每次用户请求时 , 放入用户的session中 , 如果不设置这个bean , 每个请求都会查询一次数据库 .
   */
  @Bean
  @DependsOn("lifecycleBeanPostProcessor")
  public EhCacheManager ehCacheManager() {
    EhCacheManager em = new EhCacheManager();
    em.setCacheManagerConfigFile("classpath:config/ehcache.xml");//配置文件路径
    return em;
  } 

  /**
   * LifecycleBeanPostProcessor , 这是个DestructionAwareBeanPostProcessor的子类 ,
   * 负责org.apache.shiro.util.Initializable类型bean的生命周期的 , 初始化和销毁 .
   * 主要是AuthorizingRealm类的子类 , 以及EhCacheManager类 .
   */
  @Bean(name = "lifecycleBeanPostProcessor")
  public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
  } 

  /**
   * HashedCredentialsMatcher , 这个类是为了对密码进行编码的 ,
   * 防止密码在数据库里明码保存 , 当然在登陆认证的时候 ,
   * 这个类也负责对form里输入的密码进行编码
   * 处理认证匹配处理器:如果自定义需要实现继承HashedCredentialsMatcher
   */
  @Bean(name = "hashedCredentialsMatcher")
  public HashedCredentialsMatcher hashedCredentialsMatcher() {
    HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
    credentialsMatcher.setHashAlgorithmName("MD5");//指定加密方式方式,也可以在这里加入缓存,当用户超过五次登陆错误就锁定该用户禁止不断尝试登陆
    credentialsMatcher.setHashIterations(2);
    credentialsMatcher.setStoredCredentialsHexEncoded(true);
    return credentialsMatcher;
  } 

  /**
   * AuthorizationAttributeSourceAdvisor , shiro里实现的Advisor类 ,
   * 内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法 .
   */
  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
    AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
    advisor.setSecurityManager(securityManager());
    return advisor;
  } 

  //thymeleaf模板引擎和shiro整合时使用
  @Bean
  public ShiroDialect shiroDialect() {
    return new ShiroDialect();
  }
} 

3 . 自定义Realm验证类

package com.yiyun.web.system.config;
import com.yiyun.dao.master.UserDao;
import com.yiyun.domain.UserDO;
import com.yiyun.web.common.utils.ShiroUtils;
import com.yiyun.web.system.service.MenuService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.*; 

/**
 * 获取用户的角色和权限信息
 */
public class ShiroRealm extends AuthorizingRealm { 

  // 一般这里都写的是servic
  @Autowired
  private UserDao userMapper;
  @Autowired
  private MenuService menuService; 

  /**
   * 登录认证 一般情况下 , 登录成功之后就给当前用户进行权限赋予了
   * 根据用户的权限信息做授权判断,这一步是以doGetAuthenticationInfo为基础的,只有在有用户信息后才能根据用户的角色和授权信息做判断是否给用户授权,因此这里的Roles和Permissions是用户的两个重点判断依据
   * @param authenticationToken
   * @return
   * @throws AuthenticationException
   */
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
    UserDo user = userMapper.findByName(token.getUsername());//查出是否有此用户 

    if(user != null){
      // 若存在,将此用户存放到登录认证info中,无需自己做密码对比,Shiro会为我们进行密码对比校验
      List<URole> rlist = uRoleDao.findRoleByUid(user.getId());//获取用户角色
      List<UPermission> plist = uPermissionDao.findPermissionByUid(user.getId());//获取用户权限
      List<String> roleStrlist=new ArrayList<String>();////用户的角色集合
      List<String> perminsStrlist=new ArrayList<String>();//用户的权限集合
      for (URole role : rlist) {
        roleStrlist.add(role.getName());
      }
      for (UPermission uPermission : plist) {
        perminsStrlist.add(uPermission.getName());
      }
      user.setRoleStrlist(roleStrlist);
      user.setPerminsStrlist(perminsStrlist);
      Session session = SecurityUtils.getSubject().getSession();
      session.setAttribute("user", user);//成功则放入session
      // 若存在,将此用户存放到登录认证info中,无需自己做密码对比,Shiro会为我们进行密码对比校验
      return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
    }
    return null;
  } 

  /**
   * 权限认证
   * 获取用户的权限信息,这是为下一步的授权做判断,获取当前用户的角色和这些角色所拥有的权限信息
   * @param principalCollection
   * @return
   */
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    //获取当前登录输入的用户名,等价于(String) principalCollection.fromRealm(getName()).iterator().next();
//    String loginName = (String) super.getAvailablePrincipal(principalCollection);
    UserDo user = (UserDo) principalCollection.getPrimaryPrincipal();
//    //到数据库查是否有此对象
//    User user = null;// 实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
//    user = userMapper.findByName(loginName);
    if (user != null) {
      //权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)
      SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
      //用户的角色集合
      info.addRoles(user.getRoleStrlist());
      //用户的权限集合
      info.addStringPermissions(user.getPerminsStrlist()); 

      return info;
    }
    // 返回null的话,就会导致任何用户访问被拦截的请求时,都会自动跳转到unauthorizedUrl指定的地址
    return null;
  }
} 

4 . 最后看一下ehcache的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
  updateCheck="false">
  <diskStore path="java.io.tmpdir/Tmp_EhCache" />
  <!--
    name:缓存名称。
    maxElementsInMemory:缓存最大数目
    maxElementsOnDisk:硬盘最大缓存个数。
    eternal:对象是否永久有效,一但设置了,timeout将不起作用。
    overflowToDisk:是否保存到磁盘,当系统当机时
    timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
    timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
    diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
    diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
    diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
    memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
    clearOnFlush:内存数量最大时是否清除。
     memoryStoreEvictionPolicy:
      Ehcache的三种清空策略;
      FIFO,first in first out,这个是大家最熟的,先进先出。
      LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
      LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
  --> 

  <defaultCache eternal="false" maxElementsInMemory="1000"
    overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
    timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU" />
  <!-- 登录记录缓存锁定10分钟 -->
  <cache name="passwordRetryCache"
      maxEntriesLocalHeap="2000"
      eternal="false"
      timeToIdleSeconds="3600"
      timeToLiveSeconds="0"
      overflowToDisk="false"
      statistics="true">
  </cache>
</ehcache>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • SpringBoot整合Shiro实现登录认证的方法
  • SpringBoot整合Shiro的代码详解
  • SpringBoot+Shiro学习之密码加密和登录失败次数限制示例
(0)

相关推荐

  • SpringBoot整合Shiro的代码详解

    shiro是一个权限框架,具体的使用可以查看其官网 http://shiro.apache.org/  它提供了很方便的权限认证和登录的功能. 而springboot作为一个开源框架,必然提供了和shiro整合的功能!接下来就用springboot结合springmvc,mybatis,整合shiro完成对于用户登录的判定和权限的验证. 1.准备数据库表结构 这里主要涉及到五张表:用户表,角色表(用户所拥有的角色),权限表(角色所涉及到的权限),用户-角色表(用户和角色是多对多的),角色-权限表

  • SpringBoot+Shiro学习之密码加密和登录失败次数限制示例

    这个项目写到现在,基本的雏形出来了,在此感谢一直关注的童鞋,送你们一句最近刚学习的一句鸡汤:念念不忘,必有回响.再贴一张ui图片: 前篇思考问题解决 前篇我们只是完成了同一账户的登录人数限制shiro拦截器的编写,对于手动踢出用户的功能只是说了采用在session域中添加一个key为kickout的布尔值,由之前编写的KickoutSessionControlFilter拦截器来判断是否将用户踢出,还没有说怎么获取当前在线用户的列表的核心代码,下面贴出来: /** * <p> * 服务实现类

  • SpringBoot整合Shiro实现登录认证的方法

    安全无处不在,趁着放假读了一下 Shiro 文档,并记录一下 Shiro 整合 Spring Boot 在数据库中根据角色控制访问权限 简介 Apache Shiro是一个功能强大.灵活的,开源的安全框架.它可以干净利落地处理身份验证.授权.企业会话管理和加密. 上图是 Shiro 的基本架构 Authentication(认证) 有时被称为"登录",用来证明用户是用户他们自己本人 Authorization(授权) 访问控制的过程,即确定"谁"访问"什么

  • SpringBoot集成Shiro进行权限控制和管理的示例

    shiro apache shiro 是一个轻量级的身份验证与授权框架,与spring security 相比较,简单易用,灵活性高,springboot本身是提供了对security的支持,毕竟是自家的东西.springboot暂时没有集成shiro,这得自己配. 1 . 添加依赖 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId

  • Springboot 整合shiro实现权限控制的方法

    Author:jeffrey Date:2019-04-08 一.开发环境: 1.mysql - 5.7 2.navicat(mysql客户端管理工具) 3.idea 2017.2 4.jdk8 5.tomcat 8.5 6.springboot2.1.3 7.mybatis 3 8.shiro1.4 9.maven3.3.9 二.数据库设计 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CB46ByC1-1604249108144)(img/shiro01.pn

  • SpringBoot整合Shiro实现权限控制的代码实现

    1.SpringBoot整合Shiro Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理. 1.1.shiro简介 shiro有个核心组件,分别为Subject.SecurityManager和Realms Subject:相当于当前操作的"用户",这个用户不一定是一个具体的人,是一个抽象的概念,表明的是和当前程序进行交互的任何东西,例如爬虫.脚本.等等.所有的Subject都绑定到SecurityManager上,与 Subject 的所

  • springboot集成shiro权限管理简单实现

    目录 前言 依赖 配置 Filter过滤器配置 securityManager配置 Realm配置 密码加密 测试 前言 为了解决项目当中的权限管理问题,我们一般会选择引入spring security或者shiro框架来帮助我们更好地更快地构建权限管理体系. 依赖 首先第一步,我们需要给当前项目引入对应的依赖包.与spring boot集成一般首选starter包. <!-- shiro权限管理框架 --> <dependency>    <groupId>org.a

  • springboot集成shiro遭遇自定义filter异常的解决

    目录 springboot集成shiro遭遇自定义filter异常 1.用maven添加shiro 2.配置shiro 3.实现自定义的Realm.filter.SubjectFactory等 4.重点记录filter配置中出现的问题 5.解决方案 shiro自定义异常无效 springboot集成shiro遭遇自定义filter异常 首先简述springboot使用maven集成shiro 1.用maven添加shiro <!--shiro--> <dependency> <

  • springboot集成shiro自定义登陆过滤器方法

    目录 前言 自定义UsernamePasswordAuthenticationFilter 覆盖默认的FormAuthenticationFilter 完整UsernamePasswordAuthenticationFilter代码 前言 在上一篇博客springboot集成shiro权限管理简单实现中,用户在登录的过程中,有以下几个问题: 用户在没有登陆的情况下,访问需要权限的接口,服务器自动跳转到登陆页面,前端无法控制: 用户在登录成功后,服务器自动跳转到成功页,前端无法控制: 用户在登录失

  • springboot集成shiro详细总结

    一.项目整体介绍: 项目整体的结构如下图所示,项目整体采用 springboot + mybatis + jsp + mysql 来完成的,下面会详细介绍下: 二.数据库脚本 先在数据库中创建 user.role.permission 这三张表,table.sql 的内容如下所示: DROP DATABASE IF EXISTS shiro_test; CREATE DATABASE shiro_test; USE shiro_test; SET NAMES utf8mb4; SET FOREI

  • SpringBoot整合SpringSecurity实现权限控制之实现多标签页

    目录 一.需求描述 二.前端实现 三.效果演示 四.源码 一.需求描述 多标签页 (Tabs) 的设计对于多窗口多任务管理有着无与伦比的高效率与方便性 在上面的文章中已经实现了后台管理的基本权限功能,包括用户.角色.菜单管理及权限分配. 用户通过单击侧边栏的菜单,就可以调出对应的功能页面进行使用.但在使用的过程中,我们发现程序只能在同一时间打开一个页面.我们更希望打开多个功能页面时,这些页面以标签的形式集成在同一个窗口显示,要想切换到某个页面或是关闭某个页面,我们只需要操作相应的标签即可,非常方

  • SpringBoot集成Flyway进行数据库版本迁移管理的步骤

    Flyway简介 Flyway中的迁移(migrations)模式 Flyway对数据库的所有更改都称为 migrations(迁移) . migrations(迁移) 分为版本控制(Versioned)迁移与可重复(Repeatable)的迁移两种, 而版本控制又分为regular(常规)和undo(撤销)两种形式. 版本控制迁移:具有版本号.描述和校验和,且版本是唯一的.描述用于简单记录迁移的内容,校验和用于检测意外更改. 版本控制迁移通常用于以下用途: 创建|更新|删除:表.索引.外键.枚

  • SpringBoot结合JWT登录权限控制的实现

    目录 一.准备LoginUser(存放登录用户信息) 和JwtUser 二.准备JwtTokenUtils 三.准备JWTAuthenticationFilter (验证登录).JWTAuthorizationFilter (鉴定权限)和UserDetailsServiceImpl类 (查库匹配账号密码) 四.FailHandler(账号密码错误时的处理方式) 五.配置SecurityConfig 最近项目中使用springboot+jwt实现登录权限控制,所以在这里记录一下防止以后忘记,毕竟好

随机推荐