SpringBoot整合Shiro实现登录认证和授权&&CHCache

一、 springboot实现普通登录

1 添加依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bjsxt</groupId>
    <artifactId>02_shiro_springboot_login</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--配置继承-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.10.RELEASE</version>
    </parent>
    <!--配置依赖-->
    <dependencies>
        <!--配置web启动器-->
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--配置mybatis启动器-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!--配置mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>
        <!--配置Thrmeleaf启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        

</project>

2 编写配置文件

新建application.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    url: jdbc:mysql://localhost:3306/springboot-login
    password: 1234
##配置mapper的xml文件的路径
mybatis:
  mapper-locations: classpath:mybatis/*.xml

3 新建实体类和mapper

新建com.bjsxt.pojo.User

public class User {
   private Long id;
   private String username;
   private String pwd;
   // 省略getter和setter
// 省略构造方法
}

新建com.bjsxt.mapper.UserMapper

package com.bjsxt.mapper;

public interface UserMapper {
   //根据用户名查询用户信息
   @Select("select * from t_user where uname=#{uname}")
   User selUserInfoMapper(@Param("uname") String uname);
}

4 编写业务层代码

新建com.bjsxt.service.UserService及实现类

public interface UserService {
    //用户登录
    User selUserInfoService(String uname);
}
@Service
public class UserServiceImpl implements UserService {
    //声明mapper属性
    @Autowired
    private UserMapper userMapper;
    //用户登录
    @Override
    public User selUserInfoService(String uname) {
        return userMapper.selUserInfoMapper(uname);
    }
}

5 编写控制器

新建com.bjsxt.controller.UserController

package com.bjsxt.controller;

@Controller
public class UserController {
    //声明service属性
    @Autowired
    private UserService userService;
    
    //声明单元方法:登录认证
    @RequestMapping("userLogin")
    public String userLogin(String uname,String pwd){
        //1.根据用户名获取用户信息
        User user=userService.selUserInfoService(uname);
        //2.判断用户名是否合法
        if(user!=null){
            //3.校验密码
            if(user.getPwd().equals(pwd)){
                //认证成功
                return "main";
            }
        }
        return "error";
    }
    
    //声明公共单元方法完成页面的内部转发
    @RequestMapping("{uri}")
    public String getPage(@PathVariable String uri){
        return uri;
    }

}

6 编写启动类

新建com.bjsxt.ShiroApplication

package com.bjsxt;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.bjsxt.mapper")
public class ShiroApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShiroApplication.class,args);


    }

}

7 编写登录页面和主页面

新建templates/login.html

<!DOCTYPE html>
<html  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h3>SpringBoot整合Shiro登录案例</h3>
    <hr>
    <!--创建登录页面-->
    <form action="userLogin" method="post">
        用户名: <input type="text" name="uname" value=""><br>
        密码: <input type="password" name="pwd" value=""><br>
        <input type="submit" value="登录">
    </form>

</body>
</html>

新建templates/main.html。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    我是主页面
</body>
</html>

二、 springboot整合shiro实现登录认证和凭证匹配

1 添加依赖

    <dependencies>
    
        <!-- 注释掉web启动器是因为shiro-spring-boot-web-starter依赖了spring-boot-starter-web -->
        <!-- <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>-->
        
        <!--配置shiro的启动器-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-starter</artifactId>
            <version>1.4.2</version>
        </dependency>
        
    </dependencies>

2 自定义Realm

新建com.bjsxt.shiro.MyRealm编写认证逻辑

package com.bjsxt.shiro;

//配置为Bean对象
@Component
public class MyRealm extends AuthorizingRealm {

    //声明业务层属性
    @Autowired
    private UserService userService;
    
    //自定义授权策略
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }
    
    //自定义认证策略
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //声明认证代码
                //1.获取用户传递的用户名信息
                Object principal = token.getPrincipal();
                //2.根据用户名获取数据库中的用户信息
                User user = userService.selUserInfoService((String) principal);
                //3.认证
                if(user!=null){//用户名是正确的
                    //4.认证密码
                    AuthenticationInfo info=  new SimpleAuthenticationInfo(principal,user.getPwd(), user.getUname());
                    return info;
            	}
        return null;
    }
}

3 编写配置

新建com.bjsxt.config.ShiroConfig,编写配置

package com.bjsxt.config;

@Configuration
public class ShiroConfig {
    //声明MyRealm属性
    @Autowired
    private MyRealm myRealm;
    //声明bean方法
    @Bean
    public DefaultWebSecurityManager securityManager(){
    
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(myRealm);
        
        return defaultWebSecurityManager;
    }

4 userService新增单元方法:使用shiro认证

package com.bjsxt.controller;

@Controller
public class UserController {
    
    //声明单元方法:使用shiro认证
    @RequestMapping("userLogin2")
    public String userLogin2(String uname,String pwd){
        //1.获取subject对象
            Subject subject = SecurityUtils.getSubject();
        //2.认证
            //创建认证对象存储认证信息
            AuthenticationToken token= new UsernamePasswordToken(uname,pwd);
            try{
                subject.login(token);
                return "redirect:main";
            }catch(Exception e){
                e.printStackTrace();
            }
           return "redirect:login";
    }
    
    
    //声明公共单元方法完成页面的内部转发
    @RequestMapping("{uri}")
    public String getPage(@PathVariable String uri){
        return uri;
    }

}

此时登录出现问题:访问login时报错,错误说找不到login.jsp,应该找的是login.html
解决:在ShiroConfig配置类自定义shiro过滤器参数bean

package com.bjsxt.config;

@Configuration
public class ShiroConfig {
   
    //自定义shiro过滤器参数bean
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition(){
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        definition.addPathDefinition("/login", "anon");
        definition.addPathDefinition("/userLogin", "anon");
        definition.addPathDefinition("/main", "anon");
        definition.addPathDefinition("/**", "user");
        return definition;
    }
    
}

<form action="userLogin" method="post">改为<form action="userLogin2" method="post">

<body>
    <h3>SpringBoot整合Shiro登录案例</h3>
    <hr>
    <!--创建登录页面-->
    <form action="userLogin2" method="post">
        用户名: <input type="text" name="uname" value=""><br>
        密码: <input type="password" name="pwd" value=""><br>
        <input type="submit" value="登录">
    </form>
</body>

启动测试

5 凭证匹配器

首先将数据库中用户张三的密码改为:6bdae6366c1e46d541eb0ca9547d974c

5.1 修改ShiroConfig
@Bean
public DefaultWebSecurityManager securityManager() {

    DefaultWebSecurityManager defaultWebSecurityManager= new DefaultWebSecurityManager();
    
    //创建凭证匹配器
    HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
    matcher.setHashAlgorithmName("md5");
    matcher.setHashIterations(2);
    myRealm.setCredentialsMatcher(matcher);
    
    //将自定义的认证策略对象注入到SecurityManager
    defaultWebSecurityManager.setRealm(myRealm);
    
    return defaultWebSecurityManager;
}
5.2 修改MyRealm

修改MyRealm中doGetAuthenticationInfo方法。


    //自定义认证策略
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //声明认证代码
                //1.获取用户传递的用户名信息
                Object principal = token.getPrincipal();
                //2.根据用户名获取数据库中的用户信息
                User user = userService.selUserInfoService((String) principal);
                //3.认证
                if(user!=null){//用户名是正确的
                    //4.认证密码
                    AuthenticationInfo info=  new SimpleAuthenticationInfo(principal,user.getPwd(), ByteSource.Util.bytes(user.getUid()+""),user.getUname());
                    return info;
            }
        return null;
    }

三、 remember me实现—shiro已经集成

1 修改application.yml-----增加shiro的loginUrl地址

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    url: jdbc:mysql://localhost:3306/springboot-login
    password: 1234
##配置mapper的xml文件的路径
mybatis:
  mapper-locations: classpath:mybatis/*.xml
shiro:
  ##当用户访问某个需要登录的功能时,但是被shiro内置的过滤器拦截后,判断本次请求
  ##没有登录,而是直接访问的,则重定向到loginUrl的路径资源响应给用户
  loginUrl: /login

2 增加记住我的按钮

<!DOCTYPE html>
<html  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h3>SpringBoot整合Shiro登录案例</h3>
    <hr>
    <!--创建登录页面-->
    <form action="userLogin2" method="post">
        用户名: <input type="text" name="uname" value=""><br>
        密码: <input type="password" name="pwd" value=""><br>
        <input type="submit" value="登录">
        &nbsp;&nbsp;&nbsp;&nbsp;
        <input type="checkbox" name="rememberme" value="true">记住俺
    </form>

</body>
</html>

3 修改Controller

@RequestMapping("userLogin2")
    public String userLogin2(String uname,String pwd,@RequestParam(defaultValue = "false") Boolean rememberme){
        //1.获取subject对象
            Subject subject = SecurityUtils.getSubject();
        //2.认证
            //创建认证对象存储认证信息
            AuthenticationToken token= new UsernamePasswordToken(uname,pwd,rememberme);
            try{
                subject.login(token);
                return "redirect:main";
            }catch(Exception e){
                e.printStackTrace();
            }
           return "redirect:login";
    }

4 修改ShiroConfig

	@Bean
    public DefaultWebSecurityManager securityManager(){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        
        //创建凭证匹配器
        HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();
        //设置匹配器的加密算法
        matcher.setHashAlgorithmName("md5");
        //设置匹配器的迭代加密次数
        matcher.setHashIterations(2);
        //将匹配器注入到自定义的认证策略对象中
        myRealm.setCredentialsMatcher(matcher);
        
        //将自定义的认证策略对象注入到SecurityManager
        defaultWebSecurityManager.setRealm(myRealm);
        
        //将CookieRememberMeManager对象注入到SecurityManager,开启了rememberme功能
        defaultWebSecurityManager.setCacheManager(ehCacheManager());
        
        return defaultWebSecurityManager;
    }
    
	//设置Cookie的信息
    public SimpleCookie rememberMeCookie(){
        SimpleCookie simpleCookie=new SimpleCookie("rememberMe");
        //设置有效路径
        simpleCookie.setPath("/");
        //设置声明周期
        simpleCookie.setMaxAge(30*24*60*60);
        //返回设置的cookie
        return simpleCookie;
    }

    //创建rememberMeManager对象
    public CookieRememberMeManager rememberMeManager(){
        //创建CookieRememberMeManager对象
        CookieRememberMeManager cookieRememberMeManager=new CookieRememberMeManager();
        //注入Cookie对象
        cookieRememberMeManager.setCookie(rememberMeCookie());
        //设置密钥
        cookieRememberMeManager.setCipherKey(Base64.decode("MTIzNDU2Nzg="));
        //返回
        return cookieRememberMeManager;

    }

	//自定义shiro过滤器参数bean----`definition.addPathDefinition("/**", "user");`
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition(){
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        definition.addPathDefinition("/login", "anon");
        definition.addPathDefinition("/userLogin2", "anon");
        //开启shiro内置的退出过滤器,完成退出功能
        definition.addPathDefinition("/logout", "logout");
        //definition.addPathDefinition("/main", "anon");
        definition.addPathDefinition("/**", "user");
        return definition;
    }

四、 配置退出

1 修改配置类

修改ShiroConfig类,添加logout filter 对应的url。definition.addPathDefinition("/logout", "logout");

@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
    DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
    definition.addPathDefinition("/doLogin", "anon");
    definition.addPathDefinition("/logout", "logout");
    definition.addPathDefinition("/**", "authc");
    return definition;
}

2 修改主页面

在index.html页面中添加超链接。跳转到/logout后会由shiro内置filter进行拦截。

<body>
index.html
<a href="/logout">退出</a>
</body>

五、 授权

1 简介

授权就是判断认证用户是否具有指定角色或指定权限。
Shiro可以和JSP整合也可以和Thymeleaf整合,我们讲解SpringBoot的视图技术Thymeleaf整合Shiro。
只要是授权就执行Realm的doGetAuthorizationInfo进行判断,而触发doGetAuthorizationInfo的方式,常用的就两种:
(1)在页面中通过shiro:xxxx 属性进行判断
(2)在java代码中通过注解@RequiresXXX

thymeleaf中常用属性

需要在html页面中添加属性

<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">

1.1 shiro:user=””
认证通过或已记住的用户。
1.2 shiro:authenticated=””
认证通过的用户。不包含记住的用户。
1.3 shiro:principal
输出认证用户信息。shiro:principal/
1.4 shiro:hasRole=“admin”
判断是否具有指定角色。
1.5 shiro:lacksRole=“admin”
判断是否不是没有指定角色。
1.6 shiro:hasAllRoles=“role1,role2”
判断指定角色用户是否都具有。
1.7 shiro:hasAnyRoles=“role1,role2”
只要用户具有其中一个角色就表示判断通过。
1.8 shiro:hasPermission=“userInfo:add”
是否具有指定权限。
1.9 shiro:lacksPermission=“userInfo:del”
是否不具有指定权限
1.10 shiro:hasAllPermissions=“userInfo:view, userInfo:add”
是否全具有指定权限。
1.11 shiro:hasAnyPermissions=“userInfo:view, userInfo:del”
只要有其中任何一个权限即可。

2 Thymeleaf整合shiro

2.1 添加依赖
<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.0.0</version>
</dependency>
2.2 修改配置类(负责解析thymeleaf中shiro的相关属性)
//创建解析Thymeleaf中的shiro属性的对象,由SpringBoot项目底层自动调用
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
2.3 修改Realm

绑定用户具有的角色和权限,相关数据应该是从数据库中取出。

//自定义授权策略
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //1.从数据库中获取用户的权限信息
        //2.将权限信息存储到shiro授权对象中
        System.out.println("我是授权认证方法,我被执行了");
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.addRole("role1");
        info.addRole("role2");
        info.addStringPermission("user:insert");
        info.addStringPermission("user:update");
        info.addStringPermission("sys:*");
        return info;
    }
2.4 修改main.html

访问页面后会发现“有角色”不显示,“有权限”显示。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    我是主页面
    <a href="/logout">退出</a>
    <hr>
    <span shiro:hasRole="role3">有角色</span><br>
    <span shiro:user="">shiro:user=””认证通过或已记住的用户</span><br>
    <span shiro:authenticated="">shiro:authenticated=””认证通过的用户。不包含记住的用户。</span><br>
    <hr>
    <a href="/demo">测试后台逻辑代码的授权</a>

</body>
</html>

3 使用注解判断方法是否具有权限执行

方法:可以用控制器方法,也可以是业务方法。常在控制器方法上添加注解进行判断。
常用注解:
(1)@RequiresPermissions("") 必须具有指定权限
(2)@RequiresAuthentication 必须已经认证
(3)@RequiresRoles("") 必须具有指定角色
(4)@RequiresUser 必须是已认证或记住用户
(5)@RequiresGuest 必须是访客

3.1 修改main.html

添加下面内容

<a href="/isPermission">跳转到判断权限的控制器</a>
3.2 修改UserController类
@RequestMapping("/isPermission")
@ResponseBody
@RequiresPermissions("abc:jqk")
public String isPermission(){
    return "OK";
}

当用户登录成后,点击超链接“跳转到判断权限的”超链接会出现500错误页面信息。
在这里插入图片描述

3.3 新建依赖处理类

新建com.bjsxt.controller.NoPermissionException

@ControllerAdvice
public class NoPermissionException {
    @ResponseBody
    @ExceptionHandler(UnauthorizedException.class)
    public String handleShiroException(Exception ex) {
        return "无权限";
    }
    @ResponseBody
    @ExceptionHandler(AuthorizationException.class)
    public String AuthorizationException(Exception ex) {
        return "权限认证失败";
    }
}

六 EHCache

1 ehcache简介

EHCache是sourceforge的开源缓存项目,现已经具有独立官网,网址:(http://www.ehcache.org)。其本身是纯JAVA实现的,所以可以和绝大多数Java项目无缝整合,例如:Hibernate的缓存就是基于EHCache实现的。
EHCache支持内存和磁盘缓存,默认是存储在内存中的,当内存不够时允许把缓存数据同步到磁盘中,所以不需要担心内存不够问题。
EHCache支持基于Filter的Cache实现,同时也支持Gzip压缩算法提高响应速度。

2 EHCache API演示

2.1 添加依赖

从3.0版本开始groupid为org.ehcache

<dependencies>
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
        <version>2.6.11</version>
    </dependency>
</dependencies>
2.2 新建配置文件

在src/main/resources中新建ehcache.xml。
属性含义:
maxElementsInMemory:缓存中允许创建的最大对象数。
eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
timeToIdleSeconds:缓存数据的钝化时间,取值0表示无限长。
timeToLiveSeconds:缓存数据的生存时间,取值0表示无限长。
overflowToDisk:内存不足时,是否启用磁盘缓存。
memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <!-- 磁盘缓存位置 -->
    <diskStore path="java.io.tmpdir/ehcache"/>
    <!-- 默认缓存 -->
    <defaultCache
            maxEntriesLocalHeap="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxEntriesLocalDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>
    <!-- helloworld缓存 -->
    <cache name="HelloWorldCache"
           maxElementsInMemory="1000"
           eternal="false"
           timeToIdleSeconds="5"
           timeToLiveSeconds="5"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU"/>
</ehcache>

七 Shiro和EhCache整合

Shiro支持很多第三方缓存工具。官方提供了shiro-ehcache,实现了把EHCache当做Shiro的缓存工具的解决方案。其中最好用的一个功能是就是缓存认证执行的Realm方法,减少对数据库的访问。

1 添加依赖

添加shiro-ehcache依赖。
commons-io主要是为了使用里面的工具类。本质和当前整合功能没有关系。

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>1.4.2</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

2 编写ehcache缓存配置

在resources下新建ehcache/ehcache-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="ehcache" updateCheck="false">

<!-- 磁盘缓存位置 -->
<diskStore path="java.io.tmpdir"/>
<!-- 默认缓存 -->
<defaultCache
        maxEntriesLocalHeap="1000"
        eternal="false"
        timeToIdleSeconds="3600"
        timeToLiveSeconds="3600"
        overflowToDisk="false">
</defaultCache>

<!-- 登录记录缓存 锁定10分钟 -->
<cache name="loginRecordCache"
       maxEntriesLocalHeap="2000"
       eternal="false"
       timeToIdleSeconds="600"
       timeToLiveSeconds="0"
       overflowToDisk="false"
       statistics="true">
</cache>

</ehcache>

3 修改配置文件

@Bean
public DefaultWebSecurityManager securityManager() {
    DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
    hashedCredentialsMatcher.setHashAlgorithmName("md5");
    hashedCredentialsMatcher.setHashIterations(2);
    myRealm.setCredentialsMatcher(hashedCredentialsMatcher);
    manager.setRealm(myRealm);
    manager.setRememberMeManager(rememberMeManager());
    manager.setCacheManager(getEhCacheManager());
    return manager;
}

@Bean
public EhCacheManager ehCacheManager(){
    EhCacheManager ehCacheManager = new EhCacheManager();
    InputStream is = null;
    try {
        is = ResourceUtils.getInputStreamForPath("classpath:ehcache/ehcache-shiro.xml");
    } catch (IOException e) {
        e.printStackTrace();
    }
    net.sf.ehcache.CacheManager cacheManager = new net.sf.ehcache.CacheManager(is);
    ehCacheManager.setCacheManager(cacheManager);
    return ehCacheManager;
}

八 Shiro中Session对象获取

Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("key","value");
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AloneDrifters

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

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

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

打赏作者

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

抵扣说明:

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

余额充值