增加验证码校验
This commit is contained in:
parent
59621925cf
commit
373d9f2316
8
pom.xml
8
pom.xml
|
@ -50,7 +50,7 @@
|
||||||
<!-- Mybatis Plus多表连接 -->
|
<!-- Mybatis Plus多表连接 -->
|
||||||
<mybatis.plus.join.version>1.2.4</mybatis.plus.join.version>
|
<mybatis.plus.join.version>1.2.4</mybatis.plus.join.version>
|
||||||
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
|
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
|
||||||
|
<redisson.version>3.20.0</redisson.version>
|
||||||
<app.build.name>${project.artifactId}-${project.version}</app.build.name>
|
<app.build.name>${project.artifactId}-${project.version}</app.build.name>
|
||||||
<app.build.prod>target/build</app.build.prod>
|
<app.build.prod>target/build</app.build.prod>
|
||||||
</properties>
|
</properties>
|
||||||
|
@ -268,6 +268,12 @@
|
||||||
<scope>system</scope>
|
<scope>system</scope>
|
||||||
<systemPath>${project.basedir}/lib/spire.doc.free-5.2.0.jar</systemPath>
|
<systemPath>${project.basedir}/lib/spire.doc.free-5.2.0.jar</systemPath>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.redisson</groupId>
|
||||||
|
<artifactId>redisson</artifactId>
|
||||||
|
<version>${redisson.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package com.ydool.common.config;
|
package com.ydool.common.config;
|
||||||
|
|
||||||
import com.ydool.common.interceptor.SqlLogInterceptor;
|
import com.ydool.common.interceptor.SqlLogInterceptor;
|
||||||
|
import org.redisson.Redisson;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.redisson.config.Config;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@ -10,4 +14,17 @@ public class LogConfig {
|
||||||
public SqlLogInterceptor sqlLogInterceptor() {
|
public SqlLogInterceptor sqlLogInterceptor() {
|
||||||
return new SqlLogInterceptor();
|
return new SqlLogInterceptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Value("${redis:address}")
|
||||||
|
private String address;
|
||||||
|
@Value("${redis:password}")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RedissonClient redissonClient(){
|
||||||
|
Config config = new Config();
|
||||||
|
config.useSingleServer().setAddress(address).setPassword(password);
|
||||||
|
return Redisson.create();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.ydool.common.constant;
|
||||||
|
|
||||||
|
public interface RedissonConstant {
|
||||||
|
/**
|
||||||
|
* 验证码
|
||||||
|
*/
|
||||||
|
String CAPTCHA_CODE = "lc:::oa:::captcha:::code";
|
||||||
|
/**
|
||||||
|
* ip请求验证码接口次数
|
||||||
|
*/
|
||||||
|
String CAPTCHA_CODE_COUNT = "lc:::oa:::captcha:::code:::count";
|
||||||
|
/**
|
||||||
|
* ip连续登录失败次数
|
||||||
|
*/
|
||||||
|
String LOGIN_FAIL_COUNT = "lc:::oa:::login:::fail:::count";
|
||||||
|
/**
|
||||||
|
* ip黑名单
|
||||||
|
*/
|
||||||
|
String IP_BLACK_LIST = "lc:::oa:::ip:::black:::list";
|
||||||
|
}
|
|
@ -0,0 +1,498 @@
|
||||||
|
package com.ydool.common.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.redisson.api.*;
|
||||||
|
import org.redisson.client.codec.StringCodec;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuhaoze
|
||||||
|
* @date 2023/7/17 11:00
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@ConditionalOnProperty(name = "redis.redisson.enabled", havingValue = "true")
|
||||||
|
public class RedisUtils {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedissonClient redissonClient;
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 字符串 的 RSetCache
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @return RSetCache
|
||||||
|
*/
|
||||||
|
public RSetCache<String> getSetCache(String name) {
|
||||||
|
RSetCache<String> setCache = redissonClient.getSetCache(name, StringCodec.INSTANCE);
|
||||||
|
return setCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 RSetCache 数据
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @param value 值
|
||||||
|
* @param size 缓存时间 单位:s
|
||||||
|
* @param timeUnit 缓存时间单位
|
||||||
|
* @return 是否新增成功
|
||||||
|
*/
|
||||||
|
public boolean addSetCache(String name, String value, Integer size, TimeUnit timeUnit) {
|
||||||
|
|
||||||
|
if (ObjectUtil.isNotNull(size) && ObjectUtil.isNotNull(timeUnit)) {
|
||||||
|
return this.getSetCache(name).add(value, size, timeUnit);
|
||||||
|
}
|
||||||
|
return this.getSetCache(name).add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 RSetCache 数据
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @param value 值
|
||||||
|
* @return 是否新增成功
|
||||||
|
*/
|
||||||
|
public boolean addSetCache(String name, String value) {
|
||||||
|
return this.getSetCache(name).add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 RSetCache 数据
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @param value 需要移除的值
|
||||||
|
* @return 是否移除成功
|
||||||
|
*/
|
||||||
|
public boolean removeSetCache(String name, String value) {
|
||||||
|
return this.getSetCache(name).remove(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证RSetCache里是否包含
|
||||||
|
*
|
||||||
|
* @param name 缓存name
|
||||||
|
* @param value 需要验证的值
|
||||||
|
* @return 是否包含
|
||||||
|
*/
|
||||||
|
public boolean setCacheContains(String name, String value) {
|
||||||
|
return this.getSetCache(name).contains(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新RSetCache的某个参数的缓存时间
|
||||||
|
*
|
||||||
|
* @param name 缓存name
|
||||||
|
* @param value 需要刷新缓存时间的值
|
||||||
|
* @param size 缓存时间
|
||||||
|
* @param timeUnit 缓存时间单位
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean setCacheRefresh(String name, String value, Integer size, TimeUnit timeUnit) {
|
||||||
|
this.removeSetCache(name, value);
|
||||||
|
return this.addSetCache(name, value, size, timeUnit);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 RMapCache
|
||||||
|
*
|
||||||
|
* @param name 缓存名
|
||||||
|
* @return RMapCache
|
||||||
|
*/
|
||||||
|
public RMapCache<String, Object> getMapCache(String name) {
|
||||||
|
return redissonClient.getMapCache(name, StringCodec.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 RMapCache
|
||||||
|
*
|
||||||
|
* @param name 缓存名
|
||||||
|
* @param key 键
|
||||||
|
* @return 返回 返回结果
|
||||||
|
*/
|
||||||
|
public Object getMapCache(String name, String key) {
|
||||||
|
return getMapCache(name).get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 RMapCache 数据
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @param key 键
|
||||||
|
* @param value 值
|
||||||
|
* @param size 缓存时间 单位:s
|
||||||
|
* @param timeUnit 缓存时间单位
|
||||||
|
* @return 返回 返回结果
|
||||||
|
*/
|
||||||
|
public Object putMapCache(String name, String key, Object value, Integer size, TimeUnit timeUnit) {
|
||||||
|
if (ObjectUtil.isNotNull(size) && ObjectUtil.isNotNull(timeUnit)) {
|
||||||
|
return getMapCache(name).put(key, value, size, timeUnit);
|
||||||
|
}
|
||||||
|
return getMapCache(name).put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 RMapCache 数据
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @param key 键
|
||||||
|
* @param value 值
|
||||||
|
* @return 返回 返回结果
|
||||||
|
*/
|
||||||
|
public Object putMapCache(String name, String key, Object value) {
|
||||||
|
return getMapCache(name).put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 RMapCache 数据
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @param key 键
|
||||||
|
* @return 返回 返回结果
|
||||||
|
*/
|
||||||
|
public Object removeMapCache(String name, String key) {
|
||||||
|
return getMapCache(name).remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新 RMapCache 数据
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @param key 键
|
||||||
|
* @param value 值
|
||||||
|
* @param size 缓存时间 单位:s
|
||||||
|
* @param timeUnit 缓存时间单位
|
||||||
|
* @return 返回 返回结果
|
||||||
|
*/
|
||||||
|
public Object mapCacheRefresh(String name, String key, Object value, Integer size, TimeUnit timeUnit) {
|
||||||
|
this.removeMapCache(name, key);
|
||||||
|
return this.putMapCache(name, key, value, size, timeUnit);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* 获取 字符串 的 RSet
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @return RSet
|
||||||
|
*/
|
||||||
|
public RSet<String> getSet(String name) {
|
||||||
|
RSet<String> set = redissonClient.getSet(name, StringCodec.INSTANCE);
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 RSet 数据
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @param value 值
|
||||||
|
* @return 是否新增成功
|
||||||
|
*/
|
||||||
|
public boolean addSet(String name, String value) {
|
||||||
|
return this.getSet(name).add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 RSet 数据
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @param values 值
|
||||||
|
* @return 是否新增成功
|
||||||
|
*/
|
||||||
|
public boolean addSet(String name, List<String> values) {
|
||||||
|
return this.getSet(name).addAll(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 RSet 数据
|
||||||
|
*
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @param value 需要移除的值
|
||||||
|
* @return 是否移除成功
|
||||||
|
*/
|
||||||
|
public boolean removeSet(String name, String value) {
|
||||||
|
return this.getSet(name).remove(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证是否包含
|
||||||
|
*
|
||||||
|
* @param name 缓存name
|
||||||
|
* @param value 需要验证的值
|
||||||
|
* @return 是否包含
|
||||||
|
*/
|
||||||
|
public boolean contains(String name, String value) {
|
||||||
|
return this.getSet(name).contains(value);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 RMap
|
||||||
|
*
|
||||||
|
* @param name 缓存名
|
||||||
|
* @return RMap
|
||||||
|
*/
|
||||||
|
public RMap<String, Object> getMap(String name) {
|
||||||
|
RMap<String, Object> map = redissonClient.getMap(name, StringCodec.INSTANCE);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 RMap
|
||||||
|
*
|
||||||
|
* @param name 缓存名
|
||||||
|
* @param key 键
|
||||||
|
* @return 返回 返回结果
|
||||||
|
*/
|
||||||
|
public Object getMapObject(String name, String key) {
|
||||||
|
return getMap(name).get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 RMap 数据
|
||||||
|
*
|
||||||
|
* @param name 名称
|
||||||
|
* @param key 键
|
||||||
|
* @param value 值
|
||||||
|
* @return 返回 返回结果
|
||||||
|
*/
|
||||||
|
public Object putMap(String name, String key, Object value) {
|
||||||
|
return this.getMap(name).put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 RMap 数据
|
||||||
|
*
|
||||||
|
* @param name 名称
|
||||||
|
* @param map 值
|
||||||
|
*/
|
||||||
|
public void putAllMap(String name, Map<String, Object> map) {
|
||||||
|
this.getMap(name).putAll(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 RMap 数据
|
||||||
|
*
|
||||||
|
* @param name 名称
|
||||||
|
* @param key 键
|
||||||
|
* @return 返回 返回结果
|
||||||
|
*/
|
||||||
|
public Object removeMap(String name, String key) {
|
||||||
|
return this.getMap(name).remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SET缓存
|
||||||
|
* @param name 缓存KEY
|
||||||
|
* @param value 缓存值
|
||||||
|
*/
|
||||||
|
public void set(String name, Object value) {
|
||||||
|
set(name, value, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SET缓存
|
||||||
|
* @param name 缓存KEY
|
||||||
|
* @param value 缓存值
|
||||||
|
* @param seconds 缓存秒数
|
||||||
|
*/
|
||||||
|
public void set(String name, Object value, Integer seconds) {
|
||||||
|
RBucket<Object> bucket = redissonClient.getBucket(name);
|
||||||
|
bucket.set(value);
|
||||||
|
if (seconds != null) {
|
||||||
|
bucket.expire(seconds, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET缓存 String
|
||||||
|
* @param name 缓存NAME
|
||||||
|
* @return 缓存对应的值, 不存在返回NULL
|
||||||
|
*/
|
||||||
|
public String getStr(String name) {
|
||||||
|
RBucket<String> bucket = redissonClient.getBucket(name);
|
||||||
|
if(bucket.isExists()) {
|
||||||
|
return bucket.get();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET缓存 Integer
|
||||||
|
* @param name 缓存KEY
|
||||||
|
* @return 缓存对应的值, 不存在返回NULL
|
||||||
|
*/
|
||||||
|
public Integer getInt(String name) {
|
||||||
|
RBucket<Integer> bucket = redissonClient.getBucket(name);
|
||||||
|
if(bucket.isExists()) {
|
||||||
|
return bucket.get();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从缓存中获取数据。如果缓存中不存在则从执行指定的方法获取数据,并将得到的数据同步到缓存。
|
||||||
|
*
|
||||||
|
* @param name 缓存的键。
|
||||||
|
* @param key 数据名称
|
||||||
|
* @param f 获取数据的方法。
|
||||||
|
* @return 数据对象。
|
||||||
|
*/
|
||||||
|
public String getFromCacheStr(String name, String key, Function<String, String> f) {
|
||||||
|
return this.getFromCacheStr(name, key, f, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从缓存中获取数据。如果缓存中不存在则从执行指定的方法获取数据,并将得到的数据同步到缓存。
|
||||||
|
*
|
||||||
|
* @param name 缓存的名称。
|
||||||
|
* @param key 数据key
|
||||||
|
* @param f 获取数据的方法。
|
||||||
|
* @param seconds 过期秒数。
|
||||||
|
* @return 数据对象。
|
||||||
|
*/
|
||||||
|
public String getFromCacheStr(String name, String key, Function<String, String> f, Integer seconds) {
|
||||||
|
String m;
|
||||||
|
RBucket<String> bucket = redissonClient.getBucket(name);
|
||||||
|
if (!bucket.isExists()) {
|
||||||
|
m = f.apply(key);
|
||||||
|
if (m != null) {
|
||||||
|
bucket.set(m);
|
||||||
|
if (seconds != null) {
|
||||||
|
bucket.expire(seconds, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m = bucket.get();
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从缓存中获取数据。如果缓存中不存在则从执行指定的方法获取数据,并将得到的数据同步到缓存。
|
||||||
|
*
|
||||||
|
* @param name 缓存的键。
|
||||||
|
* @param id 数据Id。
|
||||||
|
* @param f 获取数据的方法。
|
||||||
|
* @param clazz 数据对象类型。
|
||||||
|
* @return 数据对象。
|
||||||
|
*/
|
||||||
|
public <M> M getFromCache(String name, Serializable id, Function<Serializable, M> f, Class<M> clazz) {
|
||||||
|
return this.getFromCache(name, id, f, clazz, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从缓存中获取数据。如果缓存中不存在则从执行指定的方法获取数据,并将得到的数据同步到缓存。
|
||||||
|
*
|
||||||
|
* @param name 缓存的键。
|
||||||
|
* @param filter mybatis plus的过滤对象。
|
||||||
|
* @param f 获取数据的方法。
|
||||||
|
* @param clazz 数据对象类型。
|
||||||
|
* @return 数据对象。
|
||||||
|
*/
|
||||||
|
public <N> N getFromCache(
|
||||||
|
String name, LambdaQueryWrapper<N> filter, Function<LambdaQueryWrapper<N>, N> f, Class<N> clazz) {
|
||||||
|
N m;
|
||||||
|
RBucket<String> bucket = redissonClient.getBucket(name);
|
||||||
|
if (!bucket.isExists()) {
|
||||||
|
m = f.apply(filter);
|
||||||
|
if (m != null) {
|
||||||
|
bucket.set(JSONUtil.toJsonStr(m));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m = JSONUtil.toBean(bucket.get(), clazz);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从缓存中获取数据。如果缓存中不存在则从执行指定的方法获取数据,并将得到的数据同步到缓存。
|
||||||
|
*
|
||||||
|
* @param name 缓存的键。
|
||||||
|
* @param filter 过滤对象。
|
||||||
|
* @param f 获取数据的方法。
|
||||||
|
* @param clazz 数据对象类型。
|
||||||
|
* @return 数据对象。
|
||||||
|
*/
|
||||||
|
public <M, N> N getFromCache(String name, M filter, Function<M, N> f, Class<N> clazz) {
|
||||||
|
N m;
|
||||||
|
RBucket<String> bucket = redissonClient.getBucket(name);
|
||||||
|
if (!bucket.isExists()) {
|
||||||
|
m = f.apply(filter);
|
||||||
|
if (m != null) {
|
||||||
|
bucket.set(JSONUtil.toJsonStr(m));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m = JSONUtil.toBean(bucket.get(), clazz);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从缓存中获取数据。如果缓存中不存在则从执行指定的方法获取数据,并将得到的数据同步到缓存。
|
||||||
|
*
|
||||||
|
* @param name 缓存的键。
|
||||||
|
* @param id 数据Id。
|
||||||
|
* @param f 获取数据的方法。
|
||||||
|
* @param clazz 数据对象类型。
|
||||||
|
* @param seconds 过期秒数。
|
||||||
|
* @return 数据对象。
|
||||||
|
*/
|
||||||
|
public <M> M getFromCache(
|
||||||
|
String name, Serializable id, Function<Serializable, M> f, Class<M> clazz, Integer seconds) {
|
||||||
|
M m;
|
||||||
|
RBucket<String> bucket = redissonClient.getBucket(name);
|
||||||
|
if (!bucket.isExists()) {
|
||||||
|
m = f.apply(id);
|
||||||
|
if (m != null) {
|
||||||
|
bucket.set(JSONUtil.toJsonStr(m));
|
||||||
|
if (seconds != null) {
|
||||||
|
bucket.expire(seconds, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m = JSONUtil.toBean(bucket.get(), clazz);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除指定缓存。
|
||||||
|
*
|
||||||
|
* @param name 缓存名。
|
||||||
|
*/
|
||||||
|
public void evictFormCache(String name) {
|
||||||
|
redissonClient.getBucket(name).delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ public class SaTokenConfig implements WebMvcConfigurer {
|
||||||
// 注册 Sa-Token 拦截器,校验规则为 StpUtil.checkLogin() 登录校验。
|
// 注册 Sa-Token 拦截器,校验规则为 StpUtil.checkLogin() 登录校验。
|
||||||
registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
|
registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
|
||||||
.addPathPatterns(UrlConstant.API + "/**")
|
.addPathPatterns(UrlConstant.API + "/**")
|
||||||
.excludePathPatterns(UrlConstant.AUTH+"/login",UrlConstant.PERSON+"/getPersonnelRetire");
|
.excludePathPatterns(UrlConstant.AUTH+"/login",UrlConstant.PERSON+"/getPersonnelRetire",UrlConstant.AUTH+"/image");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.ydool.system.controller;
|
package com.ydool.system.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||||
|
import cn.hutool.core.lang.Dict;
|
||||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||||
import com.ydool.common.constant.UrlConstant;
|
import com.ydool.common.constant.UrlConstant;
|
||||||
|
@ -34,7 +36,7 @@ public class AuthController {
|
||||||
@ApiOperation("登录")
|
@ApiOperation("登录")
|
||||||
@ApiOperationSupport(order = 1)
|
@ApiOperationSupport(order = 1)
|
||||||
public AjaxResult login(@RequestBody @Validated AuthRequest authRequest) {
|
public AjaxResult login(@RequestBody @Validated AuthRequest authRequest) {
|
||||||
return authService.login(authRequest.getUserName(), authRequest.getPassword());
|
return authService.login(authRequest.getUserName(), authRequest.getPassword(),authRequest.getCaptchaId(),authRequest.getCaptcha());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,5 +90,17 @@ public class AuthController {
|
||||||
return authService.editSign(newSignRequest.getSign());
|
return authService.editSign(newSignRequest.getSign());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取图片验证码接口
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@GetMapping("/image")
|
||||||
|
@ApiOperation("获取图片验证码接口")
|
||||||
|
public AjaxResult captcha() {
|
||||||
|
return authService.captcha();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,12 @@ public class AuthRequest {
|
||||||
@ApiModelProperty(value = "密码", required = true)
|
@ApiModelProperty(value = "密码", required = true)
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
|
@NotBlank(message = "请输入验证码")
|
||||||
|
@ApiModelProperty(value = "验证码", required = true)
|
||||||
|
private String captcha;
|
||||||
|
|
||||||
|
@NotBlank(message = "请输入验证码ID")
|
||||||
|
@ApiModelProperty(value = "验证码ID", required = true)
|
||||||
|
private String captchaId;
|
||||||
|
|
||||||
}
|
}
|
|
@ -9,7 +9,7 @@ public interface IAuthService {
|
||||||
* @param password 密码
|
* @param password 密码
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
AjaxResult login(String userName, String password);
|
AjaxResult login(String userName, String password, String captchaId, String captcha);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登出
|
* 登出
|
||||||
|
@ -38,4 +38,6 @@ public interface IAuthService {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
AjaxResult editSign(String sign);
|
AjaxResult editSign(String sign);
|
||||||
|
|
||||||
|
AjaxResult captcha();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,22 @@ package com.ydool.system.service.impl;
|
||||||
|
|
||||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.captcha.CaptchaUtil;
|
||||||
|
import cn.hutool.captcha.LineCaptcha;
|
||||||
|
import cn.hutool.captcha.generator.RandomGenerator;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.Dict;
|
import cn.hutool.core.lang.Dict;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.ydool.common.base.BaseService;
|
import com.ydool.common.base.BaseService;
|
||||||
import com.ydool.common.cache.ConfigCache;
|
import com.ydool.common.cache.ConfigCache;
|
||||||
|
import com.ydool.common.constant.RedissonConstant;
|
||||||
import com.ydool.common.constant.UrlConstant;
|
import com.ydool.common.constant.UrlConstant;
|
||||||
import com.ydool.common.data.dto.AjaxResult;
|
import com.ydool.common.data.dto.AjaxResult;
|
||||||
import com.ydool.common.utils.CacheUtil;
|
import com.ydool.common.utils.*;
|
||||||
import com.ydool.common.utils.HttpServletUtil;
|
|
||||||
import com.ydool.common.utils.PasswordUtil;
|
|
||||||
import com.ydool.common.utils.RsaUtil;
|
|
||||||
import com.ydool.system.entity.Dept;
|
import com.ydool.system.entity.Dept;
|
||||||
import com.ydool.system.entity.Menu;
|
import com.ydool.system.entity.Menu;
|
||||||
import com.ydool.system.entity.Role;
|
import com.ydool.system.entity.Role;
|
||||||
|
@ -33,6 +35,7 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@ -46,6 +49,9 @@ public class AuthServiceImpl extends BaseService<UserMapper, User> implements IA
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeptServiceImpl deptService;
|
private DeptServiceImpl deptService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisUtils redisUtils;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录接口
|
* 登录接口
|
||||||
|
@ -56,7 +62,35 @@ public class AuthServiceImpl extends BaseService<UserMapper, User> implements IA
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult login(String userName, String password) {
|
public AjaxResult login(String userName, String password, String captchaId, String captcha) {
|
||||||
|
//获取IP
|
||||||
|
String ip = HttpServletUtil.getRemoteAddress();
|
||||||
|
//判断是否在黑名单中
|
||||||
|
boolean ipBlack = redisUtils.setCacheContains(RedissonConstant.IP_BLACK_LIST, ip);
|
||||||
|
if (ipBlack) {
|
||||||
|
//如果在黑名单中,则20分钟后再尝试
|
||||||
|
redisUtils.setCacheRefresh(RedissonConstant.IP_BLACK_LIST, ip, 20, TimeUnit.MINUTES);
|
||||||
|
return AjaxResult.fail("您的IP地址在黑名单中,请20分钟后再尝试");
|
||||||
|
}
|
||||||
|
//判断验证码是否正确
|
||||||
|
String captchaCache = (String) redisUtils.getMapCache(RedissonConstant.CAPTCHA_CODE, captchaId);
|
||||||
|
if (!captcha.equalsIgnoreCase(captchaCache)) {
|
||||||
|
//获取IP失败次数
|
||||||
|
Integer failCount = (Integer) redisUtils.getMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip);
|
||||||
|
if (ObjectUtil.isNull(failCount)) {
|
||||||
|
failCount = 1;
|
||||||
|
} else {
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
if (failCount >= 5) {
|
||||||
|
redisUtils.putMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip, failCount, 20, TimeUnit.MINUTES);
|
||||||
|
redisUtils.setCacheRefresh(RedissonConstant.IP_BLACK_LIST, ip, 20, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
return AjaxResult.fail("验证码错误");
|
||||||
|
}
|
||||||
|
//清空验证码缓存,以及验证码请求次数缓存
|
||||||
|
redisUtils.removeMapCache(RedissonConstant.CAPTCHA_CODE, captchaId);
|
||||||
|
redisUtils.removeMapCache(RedissonConstant.CAPTCHA_CODE_COUNT, ip);
|
||||||
//用户名密码按照UTF-8编码解密
|
//用户名密码按照UTF-8编码解密
|
||||||
userName = URLDecoder.decode(userName, StandardCharsets.UTF_8.name());
|
userName = URLDecoder.decode(userName, StandardCharsets.UTF_8.name());
|
||||||
password = URLDecoder.decode(password, StandardCharsets.UTF_8.name());
|
password = URLDecoder.decode(password, StandardCharsets.UTF_8.name());
|
||||||
|
@ -65,19 +99,83 @@ public class AuthServiceImpl extends BaseService<UserMapper, User> implements IA
|
||||||
password = RsaUtil.decrypt(password, UrlConstant.APP_PRIVATE_KEY);
|
password = RsaUtil.decrypt(password, UrlConstant.APP_PRIVATE_KEY);
|
||||||
//根据用户名查询账号是否存在
|
//根据用户名查询账号是否存在
|
||||||
User loginUser = getOne(new QueryWrapper<User>().lambda().eq(User::getLoginName, userName));
|
User loginUser = getOne(new QueryWrapper<User>().lambda().eq(User::getLoginName, userName));
|
||||||
if (ObjectUtil.isNull(loginUser)) return AjaxResult.fail("账号或者密码错误");
|
if (ObjectUtil.isNull(loginUser)) {
|
||||||
|
//获取IP失败次数
|
||||||
|
Integer failCount = (Integer) redisUtils.getMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip);
|
||||||
|
if (ObjectUtil.isNull(failCount)) {
|
||||||
|
failCount = 1;
|
||||||
|
} else {
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
if (failCount >= 5) {
|
||||||
|
redisUtils.putMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip, failCount, 20, TimeUnit.MINUTES);
|
||||||
|
redisUtils.setCacheRefresh(RedissonConstant.IP_BLACK_LIST, ip, 20, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
return AjaxResult.fail("账号或者密码错误");
|
||||||
|
}
|
||||||
//加密密码
|
//加密密码
|
||||||
String loginPassword = PasswordUtil.password(loginUser.getSalt(), password);
|
String loginPassword = PasswordUtil.password(loginUser.getSalt(), password);
|
||||||
//与数据库的密码进行匹配
|
//与数据库的密码进行匹配
|
||||||
if (!loginPassword.equals(loginUser.getPassword())) return AjaxResult.fail("账号或者密码错误");
|
if (!loginPassword.equals(loginUser.getPassword())) {
|
||||||
|
//获取IP失败次数
|
||||||
|
Integer failCount = (Integer) redisUtils.getMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip);
|
||||||
|
if (ObjectUtil.isNull(failCount)) {
|
||||||
|
failCount = 1;
|
||||||
|
} else {
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
if (failCount >= 5) {
|
||||||
|
redisUtils.putMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip, failCount, 20, TimeUnit.MINUTES);
|
||||||
|
redisUtils.setCacheRefresh(RedissonConstant.IP_BLACK_LIST, ip, 20, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
return AjaxResult.fail("账号或者密码错误");
|
||||||
|
}
|
||||||
//判断账号是否停用
|
//判断账号是否停用
|
||||||
if (!loginUser.getStatus()) return AjaxResult.fail("当前账号已被停用,请联系管理员");
|
if (!loginUser.getStatus()) {
|
||||||
|
//获取IP失败次数
|
||||||
|
Integer failCount = (Integer) redisUtils.getMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip);
|
||||||
|
if (ObjectUtil.isNull(failCount)) {
|
||||||
|
failCount = 1;
|
||||||
|
} else {
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
if (failCount >= 5) {
|
||||||
|
redisUtils.putMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip, failCount, 20, TimeUnit.MINUTES);
|
||||||
|
redisUtils.setCacheRefresh(RedissonConstant.IP_BLACK_LIST, ip, 20, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
return AjaxResult.fail("当前账号已被停用,请联系管理员");
|
||||||
|
}
|
||||||
|
|
||||||
//判断账号角色
|
//判断账号角色
|
||||||
if (StrUtil.isBlank(loginUser.getRoles())) return AjaxResult.fail("该用户没有对应的角色,无法登陆系统");
|
if (StrUtil.isBlank(loginUser.getRoles())) {
|
||||||
|
//获取IP失败次数
|
||||||
|
Integer failCount = (Integer) redisUtils.getMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip);
|
||||||
|
if (ObjectUtil.isNull(failCount)) {
|
||||||
|
failCount = 1;
|
||||||
|
} else {
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
if (failCount >= 5) {
|
||||||
|
redisUtils.putMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip, failCount, 20, TimeUnit.MINUTES);
|
||||||
|
redisUtils.setCacheRefresh(RedissonConstant.IP_BLACK_LIST, ip, 20, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
return AjaxResult.fail("该用户没有对应的角色,无法登陆系统");
|
||||||
|
}
|
||||||
|
|
||||||
List<Role> roleList = userService.roleListByUser(loginUser.getId());
|
List<Role> roleList = userService.roleListByUser(loginUser.getId());
|
||||||
if (CollUtil.isEmpty(roleList)) return AjaxResult.fail("该用户没有对应的角色或角色已被删除或禁用,无法登陆系统");
|
if (CollUtil.isEmpty(roleList)) { //获取IP失败次数
|
||||||
|
Integer failCount = (Integer) redisUtils.getMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip);
|
||||||
|
if (ObjectUtil.isNull(failCount)) {
|
||||||
|
failCount = 1;
|
||||||
|
} else {
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
if (failCount >= 5) {
|
||||||
|
redisUtils.putMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip, failCount, 20, TimeUnit.MINUTES);
|
||||||
|
redisUtils.setCacheRefresh(RedissonConstant.IP_BLACK_LIST, ip, 20, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
return AjaxResult.fail("该用户没有对应的角色或角色已被删除或禁用,无法登陆系统");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
loginUser.setLoginDate(LocalDateTime.now());
|
loginUser.setLoginDate(LocalDateTime.now());
|
||||||
|
@ -87,8 +185,10 @@ public class AuthServiceImpl extends BaseService<UserMapper, User> implements IA
|
||||||
StpUtil.login(loginUser.getId());
|
StpUtil.login(loginUser.getId());
|
||||||
CacheUtil.put(ConfigCache.SCHEDULED_CODE_PERSONNEL_RETIRE, ConfigCache.SCHEDULED_CODE_PERSONNEL_RETIRE, "scheduled", false);
|
CacheUtil.put(ConfigCache.SCHEDULED_CODE_PERSONNEL_RETIRE, ConfigCache.SCHEDULED_CODE_PERSONNEL_RETIRE, "scheduled", false);
|
||||||
boolean flag = updateById(loginUser);
|
boolean flag = updateById(loginUser);
|
||||||
|
|
||||||
if (flag) {
|
if (flag) {
|
||||||
|
//清空ip黑名单和登录失败次数缓存
|
||||||
|
redisUtils.removeMapCache(RedissonConstant.LOGIN_FAIL_COUNT, ip);
|
||||||
|
redisUtils.removeSetCache(RedissonConstant.IP_BLACK_LIST, ip);
|
||||||
// 第2步,获取 Token 相关参数
|
// 第2步,获取 Token 相关参数
|
||||||
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
||||||
Dict result = Dict.create();
|
Dict result = Dict.create();
|
||||||
|
@ -190,5 +290,31 @@ public class AuthServiceImpl extends BaseService<UserMapper, User> implements IA
|
||||||
return flag ? AjaxResult.ok().msg("修改电子签名成功") : AjaxResult.fail("修改电子签名失败");
|
return flag ? AjaxResult.ok().msg("修改电子签名成功") : AjaxResult.fail("修改电子签名失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AjaxResult captcha() {
|
||||||
|
//获取请求IP
|
||||||
|
String ip = HttpServletUtil.getRemoteAddress();
|
||||||
|
Integer count = (Integer) redisUtils.getMapCache(RedissonConstant.CAPTCHA_CODE_COUNT, ip);
|
||||||
|
if (count != null && count > 5) {
|
||||||
|
redisUtils.putMapCache(RedissonConstant.CAPTCHA_CODE_COUNT, ip, count + 1, 1, TimeUnit.MINUTES);
|
||||||
|
return AjaxResult.fail("验证码获取频繁,请稍后再试");
|
||||||
|
}
|
||||||
|
// 自定义纯数字的验证码(随机4位数字,可重复)
|
||||||
|
RandomGenerator randomGenerator = new RandomGenerator("0123456789", 4);
|
||||||
|
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100, 4, 30);
|
||||||
|
lineCaptcha.setGenerator(randomGenerator);
|
||||||
|
// 重新生成code
|
||||||
|
lineCaptcha.createCode();
|
||||||
|
String uuid = IdUtil.randomUUID();
|
||||||
|
String code = lineCaptcha.getCode();
|
||||||
|
String imageBase64 = lineCaptcha.getImageBase64();
|
||||||
|
Dict dict = new Dict();
|
||||||
|
dict.set("key", uuid);
|
||||||
|
dict.set("value", "data:image/jpeg;base64," + imageBase64);
|
||||||
|
redisUtils.putMapCache(RedissonConstant.CAPTCHA_CODE, uuid, code, 1, TimeUnit.MINUTES);
|
||||||
|
redisUtils.putMapCache(RedissonConstant.CAPTCHA_CODE_COUNT, ip, count == null ? 1 : count + 1, 1, TimeUnit.MINUTES);
|
||||||
|
return AjaxResult.ok().data(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,3 +119,36 @@ sa-token:
|
||||||
# token前缀
|
# token前缀
|
||||||
token-prefix: Bearer
|
token-prefix: Bearer
|
||||||
|
|
||||||
|
|
||||||
|
redis:
|
||||||
|
# redisson的配置。每个服务可以自己的配置文件中覆盖此选项。
|
||||||
|
redisson:
|
||||||
|
# 如果该值为false,系统将不会创建RedissionClient的bean。
|
||||||
|
enabled: true
|
||||||
|
# mode的可用值为,single/cluster/sentinel/master-slave
|
||||||
|
mode: single
|
||||||
|
# single: 单机模式
|
||||||
|
# address: redis://localhost:6379
|
||||||
|
# cluster: 集群模式
|
||||||
|
# 每个节点逗号分隔,同时每个节点前必须以redis://开头。
|
||||||
|
# address: redis://localhost:6379,redis://localhost:6378,...
|
||||||
|
# sentinel:
|
||||||
|
# 每个节点逗号分隔,同时每个节点前必须以redis://开头。
|
||||||
|
# address: redis://localhost:6379,redis://localhost:6378,...
|
||||||
|
# master-slave:
|
||||||
|
# 每个节点逗号分隔,第一个为主节点,其余为从节点。同时每个节点前必须以redis://开头。
|
||||||
|
# address: redis://localhost:6379,redis://localhost:6378,...
|
||||||
|
address: redis://localhost:6379
|
||||||
|
# 链接超时,单位毫秒。
|
||||||
|
timeout: 6000
|
||||||
|
# 单位毫秒。分布式锁的超时检测时长。
|
||||||
|
# 如果一次锁内操作超该毫秒数,或在释放锁之前异常退出,Redis会在该时长之后主动删除该锁使用的key。
|
||||||
|
lockWatchdogTimeout: 60000
|
||||||
|
# redis 密码,空可以不填。
|
||||||
|
password:
|
||||||
|
pool:
|
||||||
|
# 连接池数量。
|
||||||
|
poolSize: 20
|
||||||
|
# 连接池中最小空闲数量。
|
||||||
|
minIdle: 5
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue