From fb23fbb090a32ddaefb7a5d87092d034c5e0bc5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=8A=9B?= Date: Thu, 5 May 2022 15:30:10 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=AC=E9=92=A5=E7=A7=81=E9=92=A5=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=B1=BB=EF=BC=8Ctoken=E8=A7=A3=E6=9E=90=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/pom.xml | 17 +- .../storeroom/exception/BaseException.java | 10 +- .../storeroom/exception/JsonException.java | 6 +- .../storeroom/exception/PageException.java | 6 +- .../{Status.java => ResponseStatus.java} | 15 +- .../handler/GlobalExceptionHandler.java | 10 +- .../handler => utils}/ApiResponse.java | 30 +- .../java/com/storeroom/utils/CallBack.java | 12 + .../com/storeroom/utils/DataStatusConst.java | 15 + .../java/com/storeroom/utils/RedisUtils.java | 694 ++++++++++++++++++ .../java/com/storeroom/utils/RsaUtils.java | 178 +++++ .../com/storeroom/utils/SecurityUtils.java | 80 ++ .../storeroom/utils/SpringContextHolder.java | 84 +++ .../storeroom/utils/enums/DataScopeEnum.java | 32 + .../storeroom/utils/enums/DataStatusEnum.java | 25 + 15 files changed, 1177 insertions(+), 37 deletions(-) rename common/src/main/java/com/storeroom/exception/constant/{Status.java => ResponseStatus.java} (54%) rename common/src/main/java/com/storeroom/{exception/handler => utils}/ApiResponse.java (74%) create mode 100644 common/src/main/java/com/storeroom/utils/CallBack.java create mode 100644 common/src/main/java/com/storeroom/utils/DataStatusConst.java create mode 100644 common/src/main/java/com/storeroom/utils/RedisUtils.java create mode 100644 common/src/main/java/com/storeroom/utils/RsaUtils.java create mode 100644 common/src/main/java/com/storeroom/utils/SecurityUtils.java create mode 100644 common/src/main/java/com/storeroom/utils/SpringContextHolder.java create mode 100644 common/src/main/java/com/storeroom/utils/enums/DataScopeEnum.java create mode 100644 common/src/main/java/com/storeroom/utils/enums/DataStatusEnum.java diff --git a/common/pom.xml b/common/pom.xml index b38f0cd..a67276b 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -10,10 +10,23 @@ 4.0.0 common + 公共模块 - 17 - 17 + 5.3.4 + + + cn.hutool + hutool-all + ${hutool.version} + + + org.hibernate.validator + hibernate-validator + 6.1.5.Final + + + \ No newline at end of file diff --git a/common/src/main/java/com/storeroom/exception/BaseException.java b/common/src/main/java/com/storeroom/exception/BaseException.java index 82a6317..a4e9cf3 100644 --- a/common/src/main/java/com/storeroom/exception/BaseException.java +++ b/common/src/main/java/com/storeroom/exception/BaseException.java @@ -1,6 +1,6 @@ package com.storeroom.exception; -import com.storeroom.exception.constant.Status; +import com.storeroom.exception.constant.ResponseStatus; import lombok.Data; import lombok.EqualsAndHashCode; @@ -17,10 +17,10 @@ public class BaseException extends RuntimeException{ - public BaseException(Status status){ - super(status.getMessage()); - this.code=status.getCode(); - this.message=status.getMessage(); + public BaseException(ResponseStatus responseStatus){ + super(responseStatus.getMessage()); + this.code= responseStatus.getCode(); + this.message= responseStatus.getMessage(); } diff --git a/common/src/main/java/com/storeroom/exception/JsonException.java b/common/src/main/java/com/storeroom/exception/JsonException.java index e43cde4..6bbf67b 100644 --- a/common/src/main/java/com/storeroom/exception/JsonException.java +++ b/common/src/main/java/com/storeroom/exception/JsonException.java @@ -1,7 +1,7 @@ package com.storeroom.exception; -import com.storeroom.exception.constant.Status; +import com.storeroom.exception.constant.ResponseStatus; import lombok.Getter; @@ -11,8 +11,8 @@ import lombok.Getter; @Getter public class JsonException extends BaseException { - public JsonException(Status status) { - super(status); + public JsonException(ResponseStatus responseStatus) { + super(responseStatus); } public JsonException(Integer code,String message) { diff --git a/common/src/main/java/com/storeroom/exception/PageException.java b/common/src/main/java/com/storeroom/exception/PageException.java index 64c666b..a5b544f 100644 --- a/common/src/main/java/com/storeroom/exception/PageException.java +++ b/common/src/main/java/com/storeroom/exception/PageException.java @@ -1,6 +1,6 @@ package com.storeroom.exception; -import com.storeroom.exception.constant.Status; +import com.storeroom.exception.constant.ResponseStatus; import lombok.Getter; /** @@ -9,8 +9,8 @@ import lombok.Getter; @Getter public class PageException extends BaseException { - public PageException(Status status) { - super(status); + public PageException(ResponseStatus responseStatus) { + super(responseStatus); } public PageException(Integer code, String message) { diff --git a/common/src/main/java/com/storeroom/exception/constant/Status.java b/common/src/main/java/com/storeroom/exception/constant/ResponseStatus.java similarity index 54% rename from common/src/main/java/com/storeroom/exception/constant/Status.java rename to common/src/main/java/com/storeroom/exception/constant/ResponseStatus.java index 6baba42..3342e02 100644 --- a/common/src/main/java/com/storeroom/exception/constant/Status.java +++ b/common/src/main/java/com/storeroom/exception/constant/ResponseStatus.java @@ -3,15 +3,23 @@ package com.storeroom.exception.constant; import lombok.Getter; +/* + * 业务状态码类 + */ @Getter -public enum Status { +public enum ResponseStatus { //操作成功 SUCCESS(200,"操作成功"), //操作失败 FAIL(999,"操作失败"), //未知异常 - UNKNOWN_ERROR(500,"服务器内部错误"); + UNKNOWN_ERROR(500,"服务器内部错误"), + //token过期 + TOKEN_UNAUTHORIZED(4001,"当前登录状态过期"), + //token 为空 + TOKEN_IS_NULL(4002,"找不到当前登录信息"); + //状态码 @@ -21,10 +29,9 @@ public enum Status { private final String message; //构造 - Status(Integer code,String message){ + ResponseStatus(Integer code, String message){ this.code=code; this.message=message; - } } diff --git a/common/src/main/java/com/storeroom/exception/handler/GlobalExceptionHandler.java b/common/src/main/java/com/storeroom/exception/handler/GlobalExceptionHandler.java index 9d66c09..c22560e 100644 --- a/common/src/main/java/com/storeroom/exception/handler/GlobalExceptionHandler.java +++ b/common/src/main/java/com/storeroom/exception/handler/GlobalExceptionHandler.java @@ -1,13 +1,13 @@ package com.storeroom.exception.handler; import com.storeroom.exception.BaseException; -import com.storeroom.exception.constant.Status; +import com.storeroom.exception.constant.ResponseStatus; +import com.storeroom.utils.ApiResponse; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; @@ -27,20 +27,20 @@ public class GlobalExceptionHandler { @ResponseBody public ApiResponse exception(Exception e){ log.error("全局异常信息 ex={}",e.getMessage()); - return ApiResponse.error(Status.UNKNOWN_ERROR.getCode(),e.getMessage()); + return ApiResponse.error(ResponseStatus.UNKNOWN_ERROR.getCode(),e.getMessage()); } @ExceptionHandler(NullPointerException.class) @ResponseBody public ApiResponse exceptionHandler(HttpServletRequest req,NullPointerException e) { log.error("发生空指针异常!原因是:",e); - return ApiResponse.error(Status.UNKNOWN_ERROR); + return ApiResponse.error(ResponseStatus.UNKNOWN_ERROR); } @ExceptionHandler(value = Exception.class) @ResponseBody public ApiResponse exceptionHandler(HttpServletRequest req,Exception e){ log.error("未知异常 原因是:",e); - return ApiResponse.error(Status.UNKNOWN_ERROR); + return ApiResponse.error(ResponseStatus.UNKNOWN_ERROR); } } diff --git a/common/src/main/java/com/storeroom/exception/handler/ApiResponse.java b/common/src/main/java/com/storeroom/utils/ApiResponse.java similarity index 74% rename from common/src/main/java/com/storeroom/exception/handler/ApiResponse.java rename to common/src/main/java/com/storeroom/utils/ApiResponse.java index a24b29b..ae224fa 100644 --- a/common/src/main/java/com/storeroom/exception/handler/ApiResponse.java +++ b/common/src/main/java/com/storeroom/utils/ApiResponse.java @@ -1,7 +1,7 @@ -package com.storeroom.exception.handler; +package com.storeroom.utils; -import com.storeroom.exception.constant.Status; +import com.storeroom.exception.constant.ResponseStatus; import lombok.Data; /** @@ -47,22 +47,22 @@ public class ApiResponse { * @param data */ private ApiResponse(T data) { - this.code = Status.SUCCESS.getCode(); - this.message = Status.SUCCESS.getMessage(); + this.code = ResponseStatus.SUCCESS.getCode(); + this.message = ResponseStatus.SUCCESS.getMessage(); this.data = data; } /** * 无状态码构造 * - * @param status + * @param responseStatus */ - private ApiResponse(Status status) { - if (null == status) { + private ApiResponse(ResponseStatus responseStatus) { + if (null == responseStatus) { return; } - this.code = status.getCode(); - this.message = status.getMessage(); + this.code = responseStatus.getCode(); + this.message = responseStatus.getMessage(); } /** @@ -87,8 +87,8 @@ public class ApiResponse { */ public static ApiResponse success(T data) { ApiResponse apiResponse = new ApiResponse<>(); - apiResponse.setCode(Status.SUCCESS.getCode()); - apiResponse.setMessage(Status.SUCCESS.getMessage()); + apiResponse.setCode(ResponseStatus.SUCCESS.getCode()); + apiResponse.setMessage(ResponseStatus.SUCCESS.getMessage()); apiResponse.setData(data); return apiResponse; } @@ -112,12 +112,12 @@ public class ApiResponse { /** * 错误状态返回 * - * @param status 状态码 + * @param responseStatus 状态码 * @param * @return */ - public static ApiResponse error(Status status) { - return new ApiResponse(status); + public static ApiResponse error(ResponseStatus responseStatus) { + return new ApiResponse(responseStatus); } /** @@ -127,7 +127,7 @@ public class ApiResponse { * @return */ public static ApiResponse error() { - return error(Status.UNKNOWN_ERROR); + return error(ResponseStatus.UNKNOWN_ERROR); } diff --git a/common/src/main/java/com/storeroom/utils/CallBack.java b/common/src/main/java/com/storeroom/utils/CallBack.java new file mode 100644 index 0000000..a57f984 --- /dev/null +++ b/common/src/main/java/com/storeroom/utils/CallBack.java @@ -0,0 +1,12 @@ +package com.storeroom.utils; + +public interface CallBack { + + //回调执行方法 + void executor(); + + //本回调任务名称 + default String getCallBackName() { + return Thread.currentThread().getId() + ":" + this.getClass().getName(); + } +} diff --git a/common/src/main/java/com/storeroom/utils/DataStatusConst.java b/common/src/main/java/com/storeroom/utils/DataStatusConst.java new file mode 100644 index 0000000..c3a41fd --- /dev/null +++ b/common/src/main/java/com/storeroom/utils/DataStatusConst.java @@ -0,0 +1,15 @@ +package com.storeroom.utils; + + +//数据状态常量 +public class DataStatusConst { + + //正常状态 + public static final byte OK=1; + + //冻结状态码 + public static final byte FREEZED=2; + + //删除状态 + public static final byte DELETE=3; +} diff --git a/common/src/main/java/com/storeroom/utils/RedisUtils.java b/common/src/main/java/com/storeroom/utils/RedisUtils.java new file mode 100644 index 0000000..be99071 --- /dev/null +++ b/common/src/main/java/com/storeroom/utils/RedisUtils.java @@ -0,0 +1,694 @@ +package com.storeroom.utils; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.*; +import org.springframework.stereotype.Component; + +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * redis 工具类 + */ +@Component +public class RedisUtils { + private static final Logger log = LoggerFactory.getLogger(RedisUtils.class); + private RedisTemplate redisTemplate; + @Value("${jwt.online-key}") + private String onlineKey; + + public RedisUtils(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + */ + public boolean expire(String key, long time) { + try { + if (time > 0) { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + return true; + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @param timeUnit 单位 + */ + public boolean expire(String key, long time, TimeUnit timeUnit) { + try { + if (time > 0) { + redisTemplate.expire(key, time, timeUnit); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + return true; + } + + /** + * 根据 key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(Object key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 查找匹配key + * + * @param pattern key + * @return / + */ + public List scan(String pattern) { + ScanOptions options = ScanOptions.scanOptions().match(pattern).build(); + RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); + RedisConnection rc = Objects.requireNonNull(factory).getConnection(); + Cursor cursor = rc.scan(options); + List result = new ArrayList<>(); + while (cursor.hasNext()) { + result.add(new String(cursor.next())); + } + try { + RedisConnectionUtils.releaseConnection(rc, factory); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return result; + } + + /** + * 分页查询 key + * + * @param patternKey key + * @param page 页码 + * @param size 每页数目 + * @return / + */ + public List findKeysForPage(String patternKey, int page, int size) { + ScanOptions options = ScanOptions.scanOptions().match(patternKey).build(); + RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); + RedisConnection rc = Objects.requireNonNull(factory).getConnection(); + Cursor cursor = rc.scan(options); + List result = new ArrayList<>(size); + int tmpIndex = 0; + int fromIndex = page * size; + int toIndex = page * size + size; + while (cursor.hasNext()) { + if (tmpIndex >= fromIndex && tmpIndex < toIndex) { + result.add(new String(cursor.next())); + tmpIndex++; + continue; + } + // 获取到满足条件的数据后,就可以退出了 + if (tmpIndex >= toIndex) { + break; + } + tmpIndex++; + cursor.next(); + } + try { + RedisConnectionUtils.releaseConnection(rc, factory); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return result; + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 删除缓存 + * + * @param keys 可以传一个值 或多个 + */ + public void del(String... keys) { + if (keys != null && keys.length > 0) { + if (keys.length == 1) { + boolean result = redisTemplate.delete(keys[0]); + log.debug("--------------------------------------------"); + log.debug(new StringBuilder("删除缓存:").append(keys[0]).append(",结果:").append(result).toString()); + log.debug("--------------------------------------------"); + } else { + Set keySet = new HashSet<>(); + for (String key : keys) { + keySet.addAll(redisTemplate.keys(key)); + } + long count = redisTemplate.delete(keySet); + log.debug("--------------------------------------------"); + log.debug("成功删除缓存:" + keySet.toString()); + log.debug("缓存删除数量:" + count + "个"); + log.debug("--------------------------------------------"); + } + } + } + + // ============================String============================= + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 批量获取 + * + * @param keys + * @return + */ + public List multiGet(List keys) { + List list = redisTemplate.opsForValue().multiGet(Sets.newHashSet(keys)); + List resultList = Lists.newArrayList(); + Optional.ofNullable(list).ifPresent(e-> list.forEach(ele-> Optional.ofNullable(ele).ifPresent(resultList::add))); + return resultList; + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间 + * @param timeUnit 类型 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time, TimeUnit timeUnit) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, timeUnit); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + // ================================Map================================= + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * + * @param key 键 + * @param item 项 + * @param by 要增加几(大于0) + * @return + */ + public double hincr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * + * @param key 键 + * @param item 项 + * @param by 要减少记(小于0) + * @return + */ + public double hdecr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, -by); + } + + // ============================set============================= + + /** + * 根据key获取Set中的所有值 + * + * @param key 键 + * @return + */ + public Set sGet(String key) { + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + /** + * 根据value从一个set中查询,是否存在 + * + * @param key 键 + * @param value 值 + * @return true 存在 false不存在 + */ + public boolean sHasKey(String key, Object value) { + try { + return redisTemplate.opsForSet().isMember(key, value); + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将数据放入set缓存 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSet(String key, Object... values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 将set数据放入缓存 + * + * @param key 键 + * @param time 时间(秒) + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSetAndTime(String key, long time, Object... values) { + try { + Long count = redisTemplate.opsForSet().add(key, values); + if (time > 0) { + expire(key, time); + } + return count; + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 获取set缓存的长度 + * + * @param key 键 + * @return + */ + public long sGetSetSize(String key) { + try { + return redisTemplate.opsForSet().size(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 移除值为value的 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 移除的个数 + */ + public long setRemove(String key, Object... values) { + try { + Long count = redisTemplate.opsForSet().remove(key, values); + return count; + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + // ===============================list================================= + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * + * @param key 键 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public Object lGetIndex(String key, long index) { + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * + * @param key 键 + * @param index 索引 + * @param value 值 + * @return / + */ + public boolean lUpdateIndex(String key, long index, Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 移除N个值为value + * + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public long lRemove(String key, long count, Object value) { + try { + return redisTemplate.opsForList().remove(key, count, value); + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * @param prefix 前缀 + * @param ids id + */ + public void delByKeys(String prefix, Set ids) { + Set keys = new HashSet<>(); + for (Long id : ids) { + keys.addAll(redisTemplate.keys(new StringBuffer(prefix).append(id).toString())); + } + long count = redisTemplate.delete(keys); + // 此处提示可自行删除 + log.debug("--------------------------------------------"); + log.debug("成功删除缓存:" + keys.toString()); + log.debug("缓存删除数量:" + count + "个"); + log.debug("--------------------------------------------"); + } +} diff --git a/common/src/main/java/com/storeroom/utils/RsaUtils.java b/common/src/main/java/com/storeroom/utils/RsaUtils.java new file mode 100644 index 0000000..28a14d8 --- /dev/null +++ b/common/src/main/java/com/storeroom/utils/RsaUtils.java @@ -0,0 +1,178 @@ +package com.storeroom.utils; + + +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Cipher; +import java.security.*; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +/** + * 公钥私钥生成,加密工具类 + */ +public class RsaUtils { + + private static final String SRC = "123456"; + + + public static void main(String[] args) throws Exception{ + System.out.println("\n"); + RsaKeyPair keyPair = generateKeyPair(); + System.out.println("公钥:" + keyPair.getPublicKey()); + System.out.println("私钥:" + keyPair.getPrivateKey()); + System.out.println("\n"); + test1(keyPair); + System.out.println("\n"); + test2(keyPair); + System.out.println("\n"); + } + + /** + * 公钥加密私钥解密 + */ + private static void test1(RsaKeyPair keyPair) throws Exception { + System.out.println("***************** 公钥加密私钥解密开始 *****************"); + String text1 = encryptByPublicKey(keyPair.getPublicKey(), RsaUtils.SRC); + String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1); + System.out.println("加密前:" + RsaUtils.SRC); + System.out.println("加密后:" + text1); + System.out.println("解密后:" + text2); + if (RsaUtils.SRC.equals(text2)) { + System.out.println("解密字符串和原始字符串一致,解密成功"); + } else { + System.out.println("解密字符串和原始字符串不一致,解密失败"); + } + System.out.println("***************** 公钥加密私钥解密结束 *****************"); + } + + + /** + * 构建RSA密钥对 + * + * @return / + * @throws NoSuchAlgorithmException / + */ + public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(1024); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic(); + RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate(); + String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded()); + String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded()); + return new RsaKeyPair(publicKeyString, privateKeyString); + } + + /** + * 私钥加密公钥解密 + * @throws Exception / + */ + private static void test2(RsaKeyPair keyPair) throws Exception { + System.out.println("***************** 私钥加密公钥解密开始 *****************"); + String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), RsaUtils.SRC); + String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1); + System.out.println("加密前:" + RsaUtils.SRC); + System.out.println("加密后:" + text1); + System.out.println("解密后:" + text2); + if (RsaUtils.SRC.equals(text2)) { + System.out.println("解密字符串和原始字符串一致,解密成功"); + } else { + System.out.println("解密字符串和原始字符串不一致,解密失败"); + } + System.out.println("***************** 私钥加密公钥解密结束 *****************"); + } + + /** + * 公钥解密 + * + * @param publicKeyText 公钥 + * @param text 待解密的信息 + * @return / + * @throws Exception / + */ + public static String decryptByPublicKey(String publicKeyText, String text) throws Exception { + X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText)); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.DECRYPT_MODE, publicKey); + byte[] result = cipher.doFinal(Base64.decodeBase64(text)); + return new String(result); + } + + /** + * 私钥加密 + * + * @param privateKeyText 私钥 + * @param text 待加密的信息 + * @return / + * @throws Exception / + */ + public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception { + PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText)); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, privateKey); + byte[] result = cipher.doFinal(text.getBytes()); + return Base64.encodeBase64String(result); + } + + /** + * 私钥解密 + * + * @param privateKeyText 私钥 + * @param text 待解密的文本 + * @return / + * @throws Exception / + */ + public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception { + PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText)); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5); + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + byte[] result = cipher.doFinal(Base64.decodeBase64(text)); + return new String(result); + } + + /** + * 公钥加密 + * + * @param publicKeyText 公钥 + * @param text 待加密的文本 + * @return / + */ + public static String encryptByPublicKey(String publicKeyText, String text) throws Exception { + X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText)); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2); + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + byte[] result = cipher.doFinal(text.getBytes()); + return Base64.encodeBase64String(result); + } + + public static class RsaKeyPair { + + private final String publicKey; + private final String privateKey; + + public RsaKeyPair(String publicKey, String privateKey) { + this.publicKey = publicKey; + this.privateKey = privateKey; + } + + public String getPublicKey() { + return publicKey; + } + + public String getPrivateKey() { + return privateKey; + } + + } +} diff --git a/common/src/main/java/com/storeroom/utils/SecurityUtils.java b/common/src/main/java/com/storeroom/utils/SecurityUtils.java new file mode 100644 index 0000000..6d000ea --- /dev/null +++ b/common/src/main/java/com/storeroom/utils/SecurityUtils.java @@ -0,0 +1,80 @@ +package com.storeroom.utils; + + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.storeroom.exception.JsonException; +import com.storeroom.exception.constant.ResponseStatus; +import com.storeroom.utils.enums.DataScopeEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; + +import java.util.List; + +@Slf4j +public class SecurityUtils { + + /** + * 获取当前登录的用户 + * + * @return + */ + public static UserDetails getCurrentUser() { + UserDetailsService userDetailsService = SpringContextHolder.getBean(UserDetailsService.class); + return userDetailsService.loadUserByUsername(getCurrentUsername()); + } + + /** + * 获取系统用户名称 + * + * @return 系统用户名称 + */ + public static String getCurrentUsername() { + final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication == null) { + throw new JsonException(ResponseStatus.TOKEN_UNAUTHORIZED.getCode(), ResponseStatus.TOKEN_UNAUTHORIZED.getMessage()); + } + if (authentication.getPrincipal() instanceof UserDetails) { + UserDetails userDetails = (UserDetails) authentication.getPrincipal(); + return userDetails.getUsername(); + } + throw new JsonException(ResponseStatus.TOKEN_IS_NULL.getCode(), ResponseStatus.TOKEN_IS_NULL.getMessage()); + } + + /** + * 获取系统用户id + * @return + */ + public static Long getCurrentUserId() { + UserDetails userDetails = getCurrentUser(); + return new JSONObject(new JSONObject(userDetails).get("user")).get("id", Long.class); + } + + /** + * 获取当前用户的数据权限 + * @return / + */ + public static List getCurrentUserDataScope(){ + UserDetails userDetails = getCurrentUser(); + JSONArray array = JSONUtil.parseArray(new JSONObject(userDetails).get("dataScopes")); + return JSONUtil.toList(array,Long.class); + } + + /** + * 获取数据权限级别 + * @return 级别 + */ + public static String getDataScopeType() { + List dataScopes = getCurrentUserDataScope(); + if(dataScopes.size() != 0){ + return ""; + } + return DataScopeEnum.ALL.getValue(); + } + + +} diff --git a/common/src/main/java/com/storeroom/utils/SpringContextHolder.java b/common/src/main/java/com/storeroom/utils/SpringContextHolder.java new file mode 100644 index 0000000..259d951 --- /dev/null +++ b/common/src/main/java/com/storeroom/utils/SpringContextHolder.java @@ -0,0 +1,84 @@ +package com.storeroom.utils; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Component +public class SpringContextHolder implements ApplicationContextAware, DisposableBean { + + private static ApplicationContext applicationContext = null; + private static final List CALL_BACKS = new ArrayList<>(); + private static boolean addCallback = true; + + public synchronized static void addCallBacks(CallBack callBack) { + if (addCallback) { + SpringContextHolder.CALL_BACKS.add(callBack); + } else { + log.warn("CallBack:{} 已无法添加!立即执行", callBack.getCallBackName()); + callBack.executor(); + } + } + + public static T getBean(String name) { + assertContextInjected(); + return (T) applicationContext.getBean(name); + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + public static T getBean(Class requiredType) { + assertContextInjected(); + return applicationContext.getBean(requiredType); + } + + /** + * 检查App + */ + private static void assertContextInjected() { + if (applicationContext == null) { + throw new IllegalStateException("applicaitonContext属性未注入请在applicationContext\" +\n" + + "\".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder."); + } + + } + + /** + * 清除SpringContextHolder中的ApplicationContext为Null. + */ + private static void clearHolder() { + log.debug("清除SpringContextHolder中的ApplicationContext:" + + applicationContext); + applicationContext = null; + } + + @Override + public void destroy() { + SpringContextHolder.clearHolder(); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + if (SpringContextHolder.applicationContext != null) { + log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); + } + SpringContextHolder.applicationContext = applicationContext; + if (addCallback) { + for (CallBack callBack : SpringContextHolder.CALL_BACKS) { + callBack.executor(); + } + CALL_BACKS.clear(); + } + SpringContextHolder.addCallback = false; + } + + +} diff --git a/common/src/main/java/com/storeroom/utils/enums/DataScopeEnum.java b/common/src/main/java/com/storeroom/utils/enums/DataScopeEnum.java new file mode 100644 index 0000000..142abc6 --- /dev/null +++ b/common/src/main/java/com/storeroom/utils/enums/DataScopeEnum.java @@ -0,0 +1,32 @@ +package com.storeroom.utils.enums; + + +import lombok.AllArgsConstructor; +import lombok.Getter; + + +/** + * 权限等级 + */ +@Getter +@AllArgsConstructor +public enum DataScopeEnum { + + ALL("全部", "全部数据权限"), + + THIS_LEVEL("本级", "自己部门的数据权限"), + + CUSTOMIZE("自定义", "自定义数据权限"); + + private final String value; + private final String descrption; + + public static DataScopeEnum find(String val) { + for (DataScopeEnum dataScopeEnum : DataScopeEnum.values()) { + if (val.equals(dataScopeEnum.getValue())) { + return dataScopeEnum; + } + } + return null; + } +} diff --git a/common/src/main/java/com/storeroom/utils/enums/DataStatusEnum.java b/common/src/main/java/com/storeroom/utils/enums/DataStatusEnum.java new file mode 100644 index 0000000..5b75151 --- /dev/null +++ b/common/src/main/java/com/storeroom/utils/enums/DataStatusEnum.java @@ -0,0 +1,25 @@ +package com.storeroom.utils.enums; + +import com.storeroom.utils.DataStatusConst; +import lombok.Getter; + +@Getter +public enum DataStatusEnum { + + OK(DataStatusConst.OK,"正常"), + + FREEZED(DataStatusConst.FREEZED,"冻结"), + + DELETE(DataStatusConst.DELETE,"删除"); + + + private int code; + + private String message; + + DataStatusEnum(int code, String message){ + this.code=code; + this.message=message; + } + +}