1.依赖
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.2.3</version>
</dependency>
2.配置类
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
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.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.crazycake.shiro.serializer.StringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.crazycake.shiro.RedisManager;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ShiroConfigAuthentication {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private String port;
@Value("${spring.redis.timeout}")
private Integer timeout;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.database}")
private Integer database;
/**
* 过滤器 次方法可根据自己情况配置
* @param securityManager
* @return
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
Map map=new HashMap();
//anon 不用登录可以访问 authc 登录后可以访问
//静态页面
map.put("/cs/login.jsp","anon");
//登录方法
map.put("/user/login","anon");
//静态资源
map.put("/cs/**","anon");
map.put("/layui/**","anon");
// map.put("/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
shiroFilterFactoryBean.setSecurityManager(securityManager);
//认证成功跳转的页面
shiroFilterFactoryBean.setSuccessUrl("/cs/img/demo-1-bg.jpg");
//认证失败跳转的页面
shiroFilterFactoryBean.setUnauthorizedUrl("/cs/login.jsp");
return shiroFilterFactoryBean;
}
/**
* 创建 安全管理器SecurityManager
* @param dataSourceRealm
* @return
*/
@Bean
public SecurityManager getSecurityManager(Realm dataSourceRealm, SessionManager sessionManager, CacheManager redisCacheManager, CookieRememberMeManager cookieRememberMeManager){
DefaultSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(dataSourceRealm);
securityManager.setCacheManager(redisCacheManager);
// 配置 sessionManager
securityManager.setSessionManager(sessionManager);
securityManager.setRememberMeManager(cookieRememberMeManager);
return securityManager;
}
/**
* 创建Realm
* @return
*/
@Bean
public DataSourceRealm getDataSourceRealm(CacheManager cacheManager){
DataSourceRealm realm = new DataSourceRealm();
//认证缓存默认关闭
realm.setAuthenticationCachingEnabled(false);
realm.setAuthenticationCacheName("authenticationCache");
//授权缓存默认开启
realm.setAuthorizationCacheName("authorizationCache");
realm.setCacheManager(cacheManager);
return realm;
}
/**
* 配置shiro redisManager
* 使用的是shiro-redis开源插件
*
* @return
*/
@Bean
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager(); // crazycake 实现
redisManager.setHost(host+":"+port);//使用redis的ip和端口
redisManager.setTimeout(timeout); //300000等于300秒
redisManager.setDatabase(database); 默认使用0
redisManager.setPassword(password);//密码 如redis没有配置密码可取消
return redisManager;
}
@Bean
public RedisSessionDAO redisSessionDAO(RedisManager redisManager) {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager);
return redisSessionDAO;
}
@Bean
public SessionManager sessionManager(RedisSessionDAO redisSessionDAO){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//设置session超时 此时间需和redisManager设置超时时间保持一致 不然会报错
sessionManager.setGlobalSessionTimeout(timeout);
sessionManager.setDeleteInvalidSessions(true); // 删除无效session
sessionManager.setSessionDAO(redisSessionDAO);
sessionManager.setSessionIdUrlRewritingEnabled(false);
sessionManager.setSessionIdCookieEnabled(true);
return sessionManager;
}
@Bean
public RedisCacheManager redisCacheManager(RedisManager redisManager){
RedisCacheManager cacheManager = new RedisCacheManager(); // crazycake 实现
cacheManager.setRedisManager(redisManager);
cacheManager.setExpire(300);//300s
cacheManager.setKeyPrefix("shiro:cache");
cacheManager.setKeySerializer(new StringSerializer());
cacheManager.setValueSerializer(new MyRedisSerializer());
return cacheManager;
}
public SimpleCookie rememberMeCookie(){
//cookie的name,对应的默认是 JSESSIONID 如不修改会报错
SimpleCookie cookie = new SimpleCookie("shiroRedis");
cookie.setHttpOnly(true);
cookie.setPath("/"); // path为 / 用于多个系统共享JSESSIONID
cookie.setMaxAge(-1);
return cookie;
}
@Bean
public CookieRememberMeManager cookieRememberMeManager() {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
//rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
return cookieRememberMeManager;
}
配置文件
文件名 redis.properties
#地址
spring.redis.host=*******
#端口
spring.redis.port=6379
#索引库
spring.redis.database=0
#密码
spring.redis.password=****
#超时时间 300000等于300秒
spring.redis.timeout=300000
#将themilef的默认缓存禁用,热加载生效
#spring.thymeleaf.cache=false
redis.keyPrefix=0000-->
3.自定义cache序列化类 集成后缓存存进redis会正常显示
package com.jlh.complete.moudle.shiro.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.crazycake.shiro.exception.SerializationException;
import org.crazycake.shiro.serializer.RedisSerializer;
/***
* @description:
* @author:
* @date: 2019/11/29 11:50
*/
public class MyRedisSerializer<T> implements RedisSerializer<T> {
static {
//此配置不加会报类型转换异常
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);//开启AutoType
ParserConfig.getGlobalInstance().addAccept("com.codeman");//二、设置白名单
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
try {
return JSON.toJSONBytes(t, SerializerFeature.WriteClassName);
} catch (Exception ex) {
throw new SerializationException("Could not write JSON: " + ex.getMessage(), ex);
}
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
String data =new String(bytes);
T result = (T)JSON.parse(data);
return result;
}
}
4.自定义session序列化(由于session集成redis的机制是先从redis取值如果不存在则新建 这里使用上面的自定义序列化类会报空指针异常,看了源码还是不知道如何解决)
5.附一张成功图片