springboot+mybatis整合shiro 、shiro和EhCache整合

一、shiro

1.1 shiro简介

        Apache Shiro™是一个功能强大且易于使用的 Java 安全框架,它执行身份验证、授权、加密和会话管理。借助 Shiro 易于理解的 API,您可以快速轻松地保护任何应用程序——从最小的移动应用程序到最大的 Web 和企业应用程序。

https://www.infoq.com/articles/apache-shiro/

二、springboot+mybatis整合shiro 

2.1  引入jar包,生成代码(sys_user、sys_role、sys_menu)

<!--spring整合shiro包-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.9.0</version>
</dependency>

2.2 编写权限相关业务接口

服务工具类

package com.aaa.springboot.util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * @author :caicai
 * @date :Created in 2022/7/23 20:40
 * @description: 结果返回处理类
 * @modified By:
 * @version:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyReturn<T> {
    private int code;
    private String msg;
    private T data;
}
package com.aaa.springboot.util;
public enum RebStatusEnum {
    SUCCESS(1,"操作成功"),
    FAIL(-1,"操作失败"),
    PARAM_NOT_EMPTY(5001,"参数不能为空!!");
    private int code;
    private String msg;
    RebStatusEnum(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}
package com.aaa.springboot.controller;
import com.aaa.springboot.util.MyReturn;
import com.aaa.springboot.util.RebStatusEnum;
public class BaseController {
    // 传入一个原始对象,得到一个成功的返回对象
    public static <T> MyReturn getSuccess(T t){
        return new MyReturn(RebStatusEnum.SUCCESS.getCode(), RebStatusEnum.SUCCESS.getMsg(),t);
    }
    // 传入一个原始对象,得到一个失败的返回对象
    public static <T> MyReturn getFail(T t){
        return new MyReturn(RebStatusEnum.FAIL.getCode(), RebStatusEnum.FAIL.getMsg(),t);
    }
    // 异常处理 传入参数不能为空
    public static <T> MyReturn not_empty(T t){
        return new MyReturn(RebStatusEnum.PARAM_NOT_EMPTY.getCode(), RebStatusEnum.PARAM_NOT_EMPTY.getMsg(),t);
    }
}

        用户表      dao层:

public interface UserDao {
    // 根据用户名查询用户信息
    User queryByUserName(String userName);
    // 新增数据
    int insert(User user);
}

              mapper层:

<!--根据用户名查询用户信息-->
    <select id="queryByUserName" resultMap="UserMap">
        select
        user_id, dept_id, login_name, user_name, user_type, email, phonenumber, sex, avatar, password, salt, status, del_flag, login_ip, login_date, create_by, create_time, update_by, update_time, remark, role_id
        from sys_user
        where user_name = #{userName} and status=0 and del_flag=0
    </select>

    <!--新增所有列-->
    <insert id="insert" keyProperty="userId" useGeneratedKeys="true">
        insert into sys_user(dept_id, login_name, user_name, user_type, email, phonenumber, sex, avatar, password, salt, status, del_flag, login_ip, login_date, create_by, create_time, update_by, update_time, remark, role_id)
        values (#{deptId}, #{loginName}, #{userName}, #{userType}, #{email}, #{phonenumber}, #{sex}, #{avatar}, #{password}, #{salt}, #{status}, #{delFlag}, #{loginIp}, #{loginDate}, #{createBy}, #{createTime}, #{updateBy}, #{updateTime}, #{remark}, #{roleId})
    </insert>

            server层实现类

package com.aaa.springboot.service.impl;
import com.aaa.springboot.entity.PageEntity;
import com.aaa.springboot.entity.User;
import com.aaa.springboot.dao.UserDao;
import com.aaa.springboot.service.UserService;
import com.aaa.springboot.util.ConstantUtil;
import com.aaa.springboot.util.CustomException;
import com.aaa.springboot.util.MyReturn;
import com.aaa.springboot.util.RebStatusEnum;
import com.github.pagehelper.PageHelper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Sha512Hash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;
import com.github.pagehelper.PageInfo;
import javax.annotation.Resource;
import java.util.UUID;
@Service("userService")
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao userDao;
    // 根据用户名查询用户信息
    @Override
    public User queryByUserName(String userName) {
        return userDao.queryByUserName(userName);
    }
    /**
     * 用户登录
     */
    @Override
    public MyReturn login(User user) {
        if (user.getUserName() == null || user.getPassword()== null) {
            // 进行业务编写时  可以抛出自定义异常
            throw new CustomException(RebStatusEnum.PARAM_NOT_EMPTY.getCode(),
                    RebStatusEnum.PARAM_NOT_EMPTY.getMsg());
        }
        // 收集用户信息(用户名和密码)   多态
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUserName(), user.getPassword());

        // 获取当前用户
        Subject currentUser = SecurityUtils.getSubject();

        try {
            // 登录
            currentUser.login(usernamePasswordToken);
            // 获取session
            Session session = currentUser.getSession();
            // 获取登录成功后的信息  SimpleAuthenticationInfo()第一个参数
            User userInfo = (User) currentUser.getPrincipal();
            // 设置用户信息
            session.setAttribute("userInfo",userInfo);

            return new MyReturn(RebStatusEnum.SUCCESS.getCode(),RebStatusEnum.SUCCESS.getMsg(),"登录成功");
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }
        return new MyReturn(RebStatusEnum.FAIL.getCode(),RebStatusEnum.FAIL.getMsg(),"用户名或者密码错误");
    }

}

            controller层:

package com.aaa.springboot.controller;
import com.aaa.springboot.entity.PageEntity;
import com.aaa.springboot.entity.User;
import com.aaa.springboot.service.UserService;
import com.aaa.springboot.util.MyReturn;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("user")
public class UserController extends BaseController {
    /**
     * 服务对象
     */
    @Resource
    private UserService userService;

    /**
     * 登录
     */
    @GetMapping("login")
    public MyReturn login(User user){
        return userService.login(user);
    }
}

角色表       dao层:

public interface RoleDao {

    // 根据用户名查询角色信息
    List<Role> queryByUserName(String userName);
 }   

mapper层:

<!--    根据用户名查询角色信息-->
    <select id="queryByUserName" resultType="com.aaa.springboot.entity.Role">
        select * from sys_role r
        join sys_user_role ur on r.role_id = ur.role_id
        join  sys_user u on ur.user_id=u.user_id
        where r.`status`=0 and r.del_flag=0  and u.user_name=#{userName}
        and u.`status`=0 and u.del_flag=0
    </select>

server层实现类

@Service("roleService")
public class RoleServiceImpl implements RoleService {
    @Resource
    private RoleDao roleDao;

    // 根据用户名查询角色信息
    @Override
    public List<Role> queryByUserName(String userName) {
        return roleDao.queryByUserName(userName);
    }
}

菜单表    dao层

public interface MenuDao {
    // 根据用户名查询菜单信息
    List<Menu> queryByUserName(String userName);
}

mapper 层

<!--    根据用户名查询菜单信息-->
    <select id="queryByUserName" resultType="com.aaa.springboot.entity.Menu">
        select   DISTINCT m.*  from sys_menu m
        join sys_role_menu rm on m.menu_id=rm.menu_id
        join sys_user_role ur on ur.role_id=rm.role_id
        join sys_user u on u.user_id=ur.user_id
        where  m.visible=0  and u.`status`=0 and u.del_flag=0 and user_name=#{userName}
    </select>

 server层实现类

@Service("menuService")
public class MenuServiceImpl implements MenuService {
    @Resource
    private MenuDao menuDao;

    // 根据用户名查询菜单信息
    @Override
    public List<Menu> queryByUserName(String userName) {
        return menuDao.queryByUserName(userName);
    }
}

三  shiro的具体使用

https://shiro.apache.org/spring-xml.html

3.1 shiro 加密操作

3.1.1  编写SpringShiroConfig类

package com.aaa.springboot.config;

import com.aaa.springboot.util.ConstantUtil;
import com.aaa.springboot.util.MyCustomRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
/**
 * @author :caicai
 * @date :Created in 2022/8/24 14:55
 * @description:
 * @modified By:
 * @version:
 */
@Configuration  // 相当于 spring-shiro-config.xml  <beans>....</beans>
public class SpringShiroConfig {

    /**
     *   shiro过滤工厂类   拦截所有请求,交给shiro处理
     */
    @Bean  // 相当 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    public ShiroFilterFactoryBean shiroFilter(){
        // 实例化过滤工厂类
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 依赖注入securityManager()  <property name="securityManager" ref="securityManager"/>
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        // 设置认证失败后继续跳转的页面  通常都配置登录界面
        shiroFilterFactoryBean.setLoginUrl("/html/login.html");
        // 认证成功后,默认跳转界面
        //shiroFilterFactoryBean.setSuccessUrl("");
        // 设置认证成功后,访问了未授权方法跳转路径
        shiroFilterFactoryBean.setUnauthorizedUrl("/html/unauthorized.html");
        // 下面顺序不能变   不能把拦截的所有的放在放行的上面配置
        // 拦截过滤链定义 !!!!  一定要使用LinkedHashMap  要有序  如果顺序出错可能就访问不了
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 放行配置
        filterChainDefinitionMap.put("/css/**","anon");
        filterChainDefinitionMap.put("/js/**","anon");
        filterChainDefinitionMap.put("/images/**","anon");
        filterChainDefinitionMap.put("/html/login.html","anon");
        filterChainDefinitionMap.put("/user/login","anon");
        filterChainDefinitionMap.put("/user/add","anon");
        // 用户退出配置
        filterChainDefinitionMap.put("/logout","logout");
        // 除了上面的全部拦截   必须认证才能通过
        filterChainDefinitionMap.put("/**","authc");
        // 拦截过滤链定义
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        /*// shiro会拦截url中含有admin的请求  authc = org.apache.shiro.web.filter.authc.FormAuthenticationFilter 该请求必须认证后才可以访问
        //                               roles[admin]并且必须具备admin这个角色
        // 例如 http://localhost:16666/admin/queryById?id=1
        filterChainDefinitionMap.put("/admin/**","authc, roles[admin]");

        // shiro会拦截url中含有docs的请求  authc = org.apache.shiro.web.filter.authc.FormAuthenticationFilter 该请求必须认证后才可以访问
        //                               roles[admin]并且必须具备[document:read]的权限才能访问
        filterChainDefinitionMap.put("/docs/**","authc, perms[document:read]");*/
        return shiroFilterFactoryBean;
    }

    /**
     * 实例化securityManager
     */
    @Bean
    public DefaultWebSecurityManager securityManager(){
        // 实例化
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        // 依赖注入myRealm()  <property name="realm" ref="myRealm"/>
        defaultWebSecurityManager.setRealm(myCustomRealm());
        return defaultWebSecurityManager;
    }

    /**
     *  实例化 myCustomRealm
     */
    @Bean
    public MyCustomRealm myCustomRealm(){
        // 实例化
        MyCustomRealm myCustomRealm = new MyCustomRealm();
        // 依赖注入  CredentialsMatcher() 加密加盐算法
        myCustomRealm.setCredentialsMatcher(credentialsMatcher());
        return myCustomRealm;
    }

    /**
     *  定义加密加盐算法名称和计算次数
     *  实例化 HashedCredentialsMatcher
     */
    @Bean
    public HashedCredentialsMatcher credentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        // 设置加密加盐算法名称
        hashedCredentialsMatcher.setHashAlgorithmName(ConstantUtil.CredentialsMatcher.HASH_ALGORITHM_NAME);
        // 设置加密加盐 hash次数
        hashedCredentialsMatcher.setHashIterations(ConstantUtil.CredentialsMatcher.HASH_ITERATIONS);
        return hashedCredentialsMatcher;

    }
}

3.1.2  定义一个常量工具类

package com.aaa.springboot.util;
/**
 * @author :caicai
 * @date :Created in 2022/8/24 15:29
 * @description:定义有一个常量类
 * @modified By:
 * @version:
 */
public class ConstantUtil {
    /**
     * shiro的校验匹配器
     * 内部类
     */
    public interface CredentialsMatcher{
        String HASH_ALGORITHM_NAME = "SHA-512";
        int HASH_ITERATIONS = 1024;
    }
    /**
     *   还可以继续定义其他常量
     */
}

3.1.3  编写Realm

package com.aaa.springboot.util;
import com.aaa.springboot.entity.Menu;
import com.aaa.springboot.entity.Role;
import com.aaa.springboot.entity.User;
import com.aaa.springboot.service.MenuService;
import com.aaa.springboot.service.RoleService;
import com.aaa.springboot.service.UserService;
import com.alibaba.druid.util.StringUtils;
import lombok.extern.log4j.Log4j2;
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.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import javax.annotation.Resource;
import java.util.List;
/**
 * @author :caicai
 * @date :Created in 2022/8/23 13:32
 * @description: MyCustomRealm
 * @modified By:
 * @version:
 */
@Log4j2
public class MyCustomRealm extends AuthorizingRealm {
    // 依赖注入用户接口
     @Resource
     private UserService userService;
    // 如果根据用户编号查询角色集合 放入roleService
     @Resource
     private RoleService roleService;
     @Resource
     private MenuService menuService;
    /**
     *  获取授权信息数据
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取认证中的 SimpleAuthenticationInfo()第一个参数
        User user = (User) principalCollection.getPrimaryPrincipal();
        // 获取用户名
        String userName = user.getUserName();
        // 根据用户名获取当前用户对应的角色列表和菜单列表
        List<Role> roles = roleService.queryByUserName(userName);
        List<Menu> menus = menuService.queryByUserName(userName);
        // 实例化返回对象
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        // 循环遍历
        //循环添加角色集合
         for (Role role : roles) {
             log.info("角色-------------"+role.getRoleKey());
             simpleAuthorizationInfo.addRole(role.getRoleKey());
         }
        //循环添加权限集合
         for (Menu menu : menus) {
             log.info("权限-------------"+menu.getPerms());
             if (!StringUtils.isEmpty(menu.getPerms())) {
                 simpleAuthorizationInfo.addStringPermission(menu.getPerms());
             }
         }
        return simpleAuthorizationInfo;
    }
    /**
     *  获取认证信息数据
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 通过认证信息获取收集到的用户名   就是用户名 admin
        String username = authenticationToken.getPrincipal().toString();
        // 调用服务层userService 根据用户名,查询该用户的信息
        User user = userService.queryByUserName(username);
        // 判断用户是否为空,如果为空,说明用户不存在,说明用户名不对
         if (user == null){
            // 抛出账号异常
            throw new AccountException();
        }
        // 如果抛异常,说明用户名错误,程序不再执行 ,如果正确,执行下面代码
        // 获取数据库中的加密密码
         String password = user.getPassword();
        // 获取数据库中的颜值  随机  增加密码破解难道
         String salt = user.getSalt();
        //通过实例化该类,它会把从数据库中获取到的安全数据,交给SecurityManager进行认证
        //SimpleAuthenticationInfo的构造第1个参数: 把用户的信息进行传递,方便认证成功后,保存在session中使用
        //                          构造第2个参数: 数据库获取的加密密码  SecurityManager底层会进行校验
        //                          构造第3个参数: 数据库获取的加密盐值 颜值封装对象 使用盐值构造出的ByteSource
        //                          构造第4个参数: getName()获取当前realm的名称  该方法可以重写

        return new SimpleAuthenticationInfo(user,password,
                ByteSource.Util.bytes(salt),getName());
    }
}

3.1.4 编写登录及用户添加

用户登录:  登录时做认证

    /**
     * 用户登录
     */
    @Override
    public MyReturn login(User user) {
        if (user.getUserName() == null || user.getPassword()== null) {
            // 进行业务编写时  可以抛出自定义异常
            throw new CustomException(RebStatusEnum.PARAM_NOT_EMPTY.getCode(),
                    RebStatusEnum.PARAM_NOT_EMPTY.getMsg());
        }
        // 收集用户信息(用户名和密码)   多态
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUserName(), user.getPassword());

        // 获取当前用户
        Subject currentUser = SecurityUtils.getSubject();

        try {
            // 登录
            currentUser.login(usernamePasswordToken);
            // 获取session
            Session session = currentUser.getSession();
            // 获取登录成功后的信息  SimpleAuthenticationInfo()第一个参数
            User userInfo = (User) currentUser.getPrincipal();
            // 设置用户信息
            session.setAttribute("userInfo",userInfo);

            return new MyReturn(RebStatusEnum.SUCCESS.getCode(),RebStatusEnum.SUCCESS.getMsg(),"登录成功");
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }
        return new MyReturn(RebStatusEnum.FAIL.getCode(),RebStatusEnum.FAIL.getMsg(),"用户名或者密码错误");
    }

用户的添加   添加时做加盐加密

 @Override
    public User insert(User user) {
        // 获取原始密码
        String password = user.getPassword();
        // 随机盐值
        String randSalt = UUID.randomUUID().toString();
        // 使用随机颜值和原始密码加密
        Sha512Hash sha512Hash = new Sha512Hash(password,randSalt,
        ConstantUtil.CredentialsMatcher.HASH_ITERATIONS);
        // 设置 存入数据库
        user.setSalt(randSalt);
        user.setPassword(sha512Hash.toString());
        user.setStatus("0");
        user.setDelFlag("0");
        this.userDao.insert(user);
        return user;
    }

   测试结果

添加用户

 数据库中生成的颜值和密文密码

 3.2 使用注解方式为role添加shiro权限

        在角色的控制层添加下面注解

​​​​​​​       @RequiresRoles("xxx")          判断当前登录用户是否拥有某一个角色,如果有可以访问该方法,如果没有,无权访问

       @RequiresPermissions("角色 : 权限")        判断当前登录用户是否拥有某一个权限,如果有可以访问该方法,如果没有,无权访问

    // 判断当前登录用户是否拥有某一个角色,如果有可以访问该方法,如果没有,无权访问
    @RequiresRoles("guanliyuan")
    @GetMapping("queryById")
    public MyReturn queryById(Integer id) {
        return getSuccess(this.roleService.queryById(id));
    }

    // 判断当前登录用户是否拥有某一个角色,如果有可以访问该方法,如果没有,无权访问
    @RequiresRoles("dailishang")
    @GetMapping("queryByIdA")
    public MyReturn queryByIdA(Integer id) {
        return getSuccess(this.roleService.queryById(id));
    }

    // 判断当前登录用户是否拥有某一个权限,如果有可以访问该方法,如果没有,无权访问
    @RequiresPermissions("role:queryById")
    @GetMapping("queryByIdB")
    public MyReturn queryByIdB(Integer id) {
        return getSuccess(this.roleService.queryById(id));
    }

    // 判断当前登录用户是否拥有某一个权限,如果有可以访问该方法,如果没有,无权访问
    @RequiresPermissions("dept:query")
    @GetMapping("queryByIdC")
    public MyReturn queryByIdC(Integer id) {
        return getSuccess(this.roleService.queryById(id));
    }

 数据表对应关系

用户

 用户角色中间表

 角色表

 菜单表

 说明caicai这个用户具有 dailishang 这个角色  并且拥有  dept:update  和   dept:query  这两个权限

接下来对上面的代码进行测试

先使用caicai这个用户进行登录,在在地址栏中输入一下地址进行测试

http://localhost:16666/role/queryById?id=1

http://localhost:16666/role/queryByIdA?id=1

http://localhost:16666/role/queryByIdB?id=1

http://localhost:16666/role/queryByIdC?id=1

 四 shiro整合ehcache缓存

        每次我们刷新页面,或者每次进行权限验证时,都需要进行查询该用户的所有的权限数据, 花费了大量的时间,查询相同的数据。 所以,我们需要缓存。 如果我们想查询的数据,在缓存里面,就直接从缓存里面拿 ,如果缓存中不存在想查询的数据,那么才从数据库中查询。

EhCache简单入门 - 月染霜华 - 博客园

4.1 引入jar

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

4.2 在resource下添加配置ehcache.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
    />
</ehcache>

如果shiro使用xml配置的则需添加下面配置,修改securityManager注入缓存

<!-- 配置ehcache 缓存 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
</bean>

<!--SecurityManager 安全管理器配置,真正认证,授权都是它来处理-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <!--依赖注入realm-->
    <property name="realm" ref="myCustomRealm"></property>
    <!--注入缓存-->
    <property name="cacheManager" ref="cacheManager"></property>
</bean>

如果是配置类在上面配置的基础下添加下面代码

    
    /**
     * 实例化securityManager
     *  SecurityManager 安全管理器配置,真正认证,授权都是它来处理
     */
    @Bean
    public DefaultWebSecurityManager securityManager(){
        // 实例化
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        // 依赖注入myRealm()  <property name="realm" ref="myRealm"/>
        defaultWebSecurityManager.setRealm(myCustomRealm());
        //  注入缓存
        defaultWebSecurityManager.setCacheManager(ehCacheManager());

        return defaultWebSecurityManager;
    }

        @Bean
    public MyCustomRealm myCustomRealm(){
        // 实例化
        MyCustomRealm myCustomRealm = new MyCustomRealm();
        // 依赖注入  CredentialsMatcher() 加密加盐算法
        myCustomRealm.setCredentialsMatcher(credentialsMatcher());
        // 开启支持缓存,需要配置如下几个参数
        myCustomRealm.setCachingEnabled(true);
        // 启用身份验证缓存,即缓存AuthenticationInfo信息,默认false
        myCustomRealm.setAuthenticationCachingEnabled(true);
        return myCustomRealm;
    }

    /**
     *  配置ehcache 缓存
     * @return
     */
    @Bean
    public EhCacheManager ehCacheManager(){
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
        return ehCacheManager;
    }

加入缓存后第一次登录

 再次登录则不会加载上面内容

信息第一次查询时

 第二次查询  打印的日志不在显示拥有的角色权限什么的   直接在缓存中获取

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸡本蔡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值