IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> springboot+mybatis整合shiro 、shiro和EhCache整合 -> 正文阅读

[Java知识库]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;
    }

加入缓存后第一次登录

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

信息第一次查询时

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

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 00:56:31  更:2022-09-04 01:00:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:31:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码