当前位置:网站首页>Shiro integrates redis to realize distributed session processing
Shiro integrates redis to realize distributed session processing
2022-07-18 09:33:00 【Cat eating fish_】
Foregoing
In this paper shiro It has to be used in monomer applications Code based on , Give Way shiro Use Redis Manage as session , So as to realize the distributed session function .
In a clustered environment , We need multiple servers in the cluster to share cache and sessions , The current popular scheme is to use Redis Database as cache server .Shiro No official information on Redis Do cache integration support , In the official third-party extension library, there are Redis Support for : Shiro-Redis
However, this third-party extension has been updated recently 2 Years ago , Many dependencies are too low to upgrade , The following address is me fork A copy has been revised , The current version has shiro、jedis Wait for other dependencies to upgrade , We will study how to use it later fastjson2 As serialization . shiro-redis v3.7
The introduction is almost , Next, we start to use Redis As shiro The cache of .
One 、 modify POM rely on
1、 First, remove all shiro-ehcache About dependencies and code , Include pom.xml、ehcache.xml、ShiroConfig The content in
2、 introduce shiro-redis rely on
<!-- shiro Integrate redis: Here is a direct reference to the blogger who upgraded the dependency jar package -->
<dependency>
<groupId>io.github.LiJunYi2</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.7</version>
</dependency>
<!-- springboot Integrate redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-extension</artifactId>
<version>2.0.9</version>
</dependency>
Copy code Two 、Yaml newly added Redis Configuration of
spring:
redis:
database: 0
host: 127.0.0.1
port: 6379
password:
timeout: 6000ms
lettuce:
pool:
max-active: 1000
max-wait: -1ms
max-idle: 10
min-idle: 5
Copy code 3、 ... and 、 newly added Redis Serialization configuration
What we use here is FastJson2
/** * @className: FastJson2JsonRedisSerializer * @description: Redis Use FastJson serialize */
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
{
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
private Class<T> clazz;
public FastJson2JsonRedisSerializer(Class<T> clazz)
{
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException
{
if (t == null)
{
return new byte[0];
}
return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException
{
if (bytes == null || bytes.length <= 0)
{
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType);
}
}
Copy code /** * @className: RedisConfig * @description: redis Serialization configuration */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport
{
@Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
{
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
// Use StringRedisSerializer To serialize and deserialize redis Of key value
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
// Hash Of key Also used StringRedisSerializer How to serialize
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
Copy code Four 、 modify shiro Configuration of
@Configuration
public class ShiroConfig {
/** * redis Cache address */
@Value("${spring.redis.port}")
private String redisPort;
/** * redis Cache port */
@Value("${spring.redis.host}")
private String redisHost;
/** * redis Database index */
@Value("${spring.redis.database}")
private int database;
/** * redis password */
@Value("${spring.redis.password}")
private String password;
/** * Login address */
@Value("${shiro.user.loginUrl}")
private String loginUrl;
/** * The success of url */
@Value("${shiro.user.successUrl}")
private String successUrl;
/** * Unauthorized url */
@Value("${shiro.user.unauthorizedUrl}")
private String unauthorizedUrl;
/** * Cache Manager (shiro-redis) */
@Bean
public RedisCacheManager redisCacheManager()
{
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
redisCacheManager.setPrincipalIdFieldName("loginName");
redisCacheManager.setValueSerializer(new FstSerializer());
return redisCacheManager;
}
/** * RedisManager (shiro-redis) */
@Bean
public IRedisManager redisManager()
{
LettuceRedisManager redisManager = new LettuceRedisManager(redisHost, Convert.toInt(redisPort));
redisManager.setDatabase(database);
redisManager.setTimeout(30 * 60);
return redisManager;
}
/** * Customize Realm */
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm shiroRealm = new MyShiroRealm();
shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
shiroRealm.setCacheManager(redisCacheManager());
return shiroRealm;
}
/** * Voucher matching machine ( Due to our password check handed Shiro Of SimpleAuthenticationInfo processed * So we need to revise that doGetAuthenticationInfo The code in ; ) */
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
// Hash algorithm : Use here MD5 Algorithm ;
hashedCredentialsMatcher.setHashAlgorithmName("md5");
hashedCredentialsMatcher.setHashIterations(1024);
return hashedCredentialsMatcher;
}
/** * Exit the filter */
public LogoutFilter logoutFilter(){
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setLoginUrl(loginUrl);
logoutFilter.setCacheManager(redisCacheManager());
return logoutFilter;
}
/** * RedisSessionDAO (shiro-redis) */
@Bean
public RedisSessionDAO redisSessionDAO()
{
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
// custom session key prefix
//redisSessionDAO.setKeyPrefix("");
// custom session value serializer, default is jdk serializer.
redisSessionDAO.setValueSerializer(new FstSerializer());
redisSessionDAO.setExpire(30 * 60);
return redisSessionDAO;
}
/** * Session manager */
@Bean
public SessionManager sessionManager(){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
// Join cache manager
sessionManager.setCacheManager(redisCacheManager());
// Get rid of JSESSIONID
sessionManager.setSessionIdUrlRewritingEnabled(false);
sessionManager.setSessionIdCookie(simpleCookie());
// Customize SessionDao
sessionManager.setSessionDAO(redisSessionDAO());
return sessionManager;
}
/** * Safety manager securityManager */
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
// Inject cache manager
securityManager.setCacheManager(redisCacheManager());
// Inject remember me manager
securityManager.setRememberMeManager(rememberMeManager());
// Inject session management
securityManager.setSessionManager(sessionManager());
return securityManager;
}
/** * Shiro Filter configuration * */
@Bean
public ShiroFilterFactoryBean shiroFilter(){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// You have to set SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager());
// ......
return shiroFilterFactoryBean;
}
private SimpleCookie simpleCookie()
{
SimpleCookie simpleCookie = new SimpleCookie("shiro.sesssion");
simpleCookie.setPath("/");
return simpleCookie;
}
/** * cookie Property settings */
private SimpleCookie rememberMeCookie(){
// This parameter is cookie The name of , Corresponding to the front end checkbox Of name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
// If httyOnly Set to true, Then the client will not be exposed to the client script code
simpleCookie.setHttpOnly(true);
simpleCookie.setMaxAge(-1);
simpleCookie.setPath("/");
return simpleCookie;
}
/** rememberMeManager Manager * rememberMeManager() The method is to generate rememberMe Manager , And I'm going to put this rememberMe Manager settings to securityManager in */
private CookieRememberMeManager rememberMeManager(){
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCipherKey(Base64.decode("xxxxxx"));
cookieRememberMeManager.setCookie(rememberMeCookie());
return cookieRememberMeManager;
}
/** * Session scheduler */
@Bean
public ExecutorServiceSessionValidationScheduler scheduler(){
ExecutorServiceSessionValidationScheduler scheduler = new ExecutorServiceSessionValidationScheduler();
scheduler.setInterval(30 * 60 * 1000);
return scheduler;
}
/** * Multiple device login restrictions for the same user */
public KickoutSessionControlFilter kickoutSessionControlFilter(){
KickoutSessionControlFilter kickoutSessionControlFilter = new KickoutSessionControlFilter();
kickoutSessionControlFilter.setCacheManager(redisCacheManager());
kickoutSessionControlFilter.setSessionManager(sessionManager());
// The maximum number of sessions for the same user , Default -1 unlimited ; such as 2 It means that the same user can allow up to two people to log in at the same time
kickoutSessionControlFilter.setMaxSession(1);
// Whether to kick out the later login , The default is false; That is, the user logged in by the latter kicks out the user logged in by the former ; Kick out order
kickoutSessionControlFilter.setKickoutAfter(false);
kickoutSessionControlFilter.setKickoutUrl("/login?kickout=1");
return kickoutSessionControlFilter;
}
/** * stay thymeleaf Use shiro Page TAB * */
@Bean
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}
/** * Turn on Shiro Annotation Notifier */
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
/** * DefaultAdvisorAutoProxyCreator,Spring One of the bean, from Advisor Decide which class's methods should be modified AOP agent . */
@Bean
@ConditionalOnMissingBean
public static DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultApp = new DefaultAdvisorAutoProxyCreator();
defaultApp.setProxyTargetClass(true);
return defaultApp;
}
}
Copy code test
After starting and logging into the system , see redis Cache of console
Other articles
边栏推荐
猜你喜欢

Seven reasons why Ubuntu 22.04 LTS is the safest version at present

Codeforces Round #804 C The Third Problem

5-Redis架构设计到使用场景-存储原理-数据类型底层结构

A few minutes before work, I thoroughly understood json stringify()

Codeforces Round #802 B. Palindromic Numbers

Scenarios that must be considered when designing a stable microservice system

Codeforces Round #803 (Div. 2) B. Rising Sand

Leetcode-62-different paths

LeetCode-128-最长连续序列

【空间&单细胞组学】第2期:乳腺癌患者经anti-PD1治疗后,肿瘤内变化的单细胞图谱
随机推荐
Win11系统.NET Framework 3.5怎么启用?
Nest framework
量子保密通信浅析
Unity Shader——CGInclude文件cginc
BTC与科技股相关性减弱 市场不确定性增强?53%投资者将转向另类资产
网络信息查看及配置
CSDN blog expert exclusive honor award is coming
Access control settings
Tengshi's new luxury medium and large MPV is exposed, safe and comfortable
Is it safe for Huatai Securities to open an account online? Is the fund guaranteed?
Idea导入jar包操作以及xml file配置文件
Airiot Q & A issue 4 | how to use data analysis engine?
微服务学习
怎么解决系统高并发问题的思路?看完你就彻底懂了。
LeetCode-83-删除链表中的重复元素
Opengauss cooperates with industry innovation to build a root community of open source databases
Codeforces Round #802 D. River Locks
Codeforces Round #803 (Div. 2) B. Rising Sand
华泰证券开户,真的安全吗?
Codeforces Round #804 C The Third Problem