diff --git a/README.md b/README.md index 84870668b251cc3866ea3b6d014d7679ad94ce04..9ff24560879cb8f5f0e75ca67c9c5d607f408b3f 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,8 @@ secret-boot脚手架(根据核心依赖版本长期更新,正常更新周期 com.gitee.secretopen - secret-boot-framework - 1.4.0 + secret-boot-framework-dependencies + 1.5.0 pom import @@ -54,7 +54,7 @@ secret-boot脚手架(根据核心依赖版本长期更新,正常更新周期 com.gitee.secretopen secret-boot-framework-all - 1.4.0 + 1.5.0 ``` diff --git a/secret-boot-framework-cache/pom.xml b/secret-boot-framework-cache/pom.xml index ad361e565f476c0da765d5801cebcff026ca0add..e611448fccc4a5fd5966692983fd087d2714c88a 100644 --- a/secret-boot-framework-cache/pom.xml +++ b/secret-boot-framework-cache/pom.xml @@ -23,6 +23,10 @@ org.springframework.boot spring-boot-starter-data-redis + + org.redisson + redisson-spring-boot-starter + diff --git a/secret-boot-framework-cache/src/main/java/cn/chenc/framework/cache/util/RedissLockUtil.java b/secret-boot-framework-cache/src/main/java/cn/chenc/framework/cache/util/RedissLockUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..5e174f0a123cd5e74f3d2f0d51f4ebde2d61f7a0 --- /dev/null +++ b/secret-boot-framework-cache/src/main/java/cn/chenc/framework/cache/util/RedissLockUtil.java @@ -0,0 +1,149 @@ +package cn.chenc.framework.cache.util; + +import org.redisson.api.RLock; +import org.redisson.api.RMapCache; +import org.redisson.api.RedissonClient; + +import java.util.concurrent.TimeUnit; + +/** + *  @description: redis分布式锁 + *  @author secret + *  @date 2021/5/7 15:27 + * + */ +public class RedissLockUtil { + + private static RedissonClient redissonClient; + + public void setRedissonClient(RedissonClient locker) { + redissonClient = locker; + } + + /** + * 加锁 + * @param lockKey + * @return + */ + public static RLock lock(String lockKey) { + RLock lock = redissonClient.getLock(lockKey); + lock.lock(); + return lock; + } + + /** + * 释放锁 + * @param lockKey + */ + public static void unlock(String lockKey) { + RLock lock = redissonClient.getLock(lockKey); + lock.unlock(); + } + + /** + * 释放锁 + * @param lock + */ + public static void unlock(RLock lock) { + lock.unlock(); + } + + /** + * 带超时的锁 + * @param lockKey + * @param timeout 超时时间 单位:秒 + */ + public static RLock lock(String lockKey, int timeout) { + RLock lock = redissonClient.getLock(lockKey); + lock.lock(timeout, TimeUnit.SECONDS); + return lock; + } + + /** + * 带超时的锁 + * @param lockKey + * @param unit 时间单位 + * @param timeout 超时时间 + */ + public static RLock lock(String lockKey, TimeUnit unit, int timeout) { + RLock lock = redissonClient.getLock(lockKey); + lock.lock(timeout, unit); + return lock; + } + + /** + * 尝试获取锁 + * @param lockKey + * @param waitTime 最多等待时间 + * @param leaseTime 上锁后自动释放锁时间 + * @return + */ + public static boolean tryLock(String lockKey, int waitTime, int leaseTime) { + RLock lock = redissonClient.getLock(lockKey); + try { + return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS); + } catch (InterruptedException e) { + return false; + } + } + + /** + * 尝试获取锁 + * @param lockKey + * @param unit 时间单位 + * @param waitTime 最多等待时间 + * @param leaseTime 上锁后自动释放锁时间 + * @return + */ + public static boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) { + RLock lock = redissonClient.getLock(lockKey); + try { + return lock.tryLock(waitTime, leaseTime, unit); + } catch (InterruptedException e) { + return false; + } + } + + /** + * 初始红包数量 + * @param key + * @param count + */ + public void initCount(String key,int count) { + RMapCache mapCache = redissonClient.getMapCache("skill"); + mapCache.putIfAbsent(key,count,3,TimeUnit.DAYS); + } + + /** + * 递增 + * @param key + * @param delta 要增加几(大于0) + * @return + */ + public int incr(String key, int delta) { + RMapCache mapCache = redissonClient.getMapCache("skill"); + if (delta < 0) { + throw new RuntimeException("递增因子必须大于0"); + } + return mapCache.addAndGet(key, 1);//加1并获取计算后的值 + } + + /** + * 递减 + * @param key 键 + * @param delta 要减少几(小于0) + * @return + */ + public int decr(String key, int delta) { + RMapCache mapCache = redissonClient.getMapCache("skill"); + if (delta < 0) { + throw new RuntimeException("递减因子必须大于0"); + } + return mapCache.addAndGet(key, -delta);//加1并获取计算后的值 + } + + public static RedissonClient getRedissonClient() { + return redissonClient; + } + +} diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/annotation/PreAuthorize.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/annotation/PreAuthorize.java new file mode 100644 index 0000000000000000000000000000000000000000..085961eb759ce3e7c374275bfa7aadbf447c505d --- /dev/null +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/annotation/PreAuthorize.java @@ -0,0 +1,44 @@ +package cn.chenc.framework.core.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 权限注解 + * + */ +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface PreAuthorize { + /** + * 验证用户是否具备某权限 + */ + public String hasPermi() default ""; + + /** + * 验证用户是否不具备某权限,与 hasPermi逻辑相反 + */ + public String lacksPermi() default ""; + + /** + * 验证用户是否具有以下任意一个权限 + */ + public String[] hasAnyPermi() default {}; + + /** + * 判断用户是否拥有某个角色 + */ + public String hasRole() default ""; + + /** + * 验证用户是否不具备某角色,与 isRole逻辑相反 + */ + public String lacksRole() default ""; + + /** + * 验证用户是否具有以下任意一个角色 + */ + public String[] hasAnyRoles() default {}; +} diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/aspect/PreAuthorizeAspect.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/aspect/PreAuthorizeAspect.java new file mode 100644 index 0000000000000000000000000000000000000000..b59add1600bb0d2e0d4364a2dadc8a6fe599bb3c --- /dev/null +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/aspect/PreAuthorizeAspect.java @@ -0,0 +1,195 @@ +package cn.chenc.framework.core.aspect; + +import cn.chenc.framework.core.annotation.PreAuthorize; +import cn.chenc.framework.core.component.JwtTemplate; +import cn.chenc.framework.core.exception.PreAuthorizeException; +import cn.chenc.framework.core.model.LoginUser; +import cn.chenc.framework.core.model.request.RequestHolder; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.springframework.util.PatternMatchUtils; +import org.springframework.util.StringUtils; + +import java.lang.reflect.Method; +import java.util.Collection; + +/** + * 自定义权限实现 + * + * @author secret + */ +@Aspect +@Component +public class PreAuthorizeAspect { + + @Autowired(required = false) + private JwtTemplate jwtTemplate; + + /** 所有权限标识 */ + private static final String ALL_PERMISSION = "*:*:*"; + + /** 管理员角色权限标识 */ + private static final String SUPER_ADMIN = "admin"; + + /** 数组为0时 */ + private static final Integer ARRAY_EMPTY = 0; + + @Around("@annotation(cn.chenc.framework.core.annotation.PreAuthorize)") + public Object around(ProceedingJoinPoint point) throws Throwable { + Signature signature = point.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + Method method = methodSignature.getMethod(); + PreAuthorize annotation = method.getAnnotation(PreAuthorize.class); + if (annotation == null) { + return point.proceed(); + } + if (!StringUtils.isEmpty(annotation.hasPermi())) { + if (hasPermi(annotation.hasPermi())) { + return point.proceed(); + } + throw new PreAuthorizeException(); + } + else if (!StringUtils.isEmpty(annotation.lacksPermi())) { + if (lacksPermi(annotation.lacksPermi())) { + return point.proceed(); + } + throw new PreAuthorizeException(); + } + else if (ARRAY_EMPTY < annotation.hasAnyPermi().length) { + if (hasAnyPermi(annotation.hasAnyPermi())) { + return point.proceed(); + } + throw new PreAuthorizeException(); + } + else if (!StringUtils.isEmpty(annotation.hasRole())) { + if (hasRole(annotation.hasRole())) { + return point.proceed(); + } + throw new PreAuthorizeException(); + } + else if (!StringUtils.isEmpty(annotation.lacksRole())) { + if (lacksRole(annotation.lacksRole())) { + return point.proceed(); + } + throw new PreAuthorizeException(); + } + else if (ARRAY_EMPTY < annotation.hasAnyRoles().length) { + if (hasAnyRoles(annotation.hasAnyRoles())) { + return point.proceed(); + } + throw new PreAuthorizeException(); + } + + return point.proceed(); + } + + /** + * 验证用户是否具备某权限 + * + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + public boolean hasPermi(String permission) { + LoginUser userInfo = jwtTemplate.getLoginUser(RequestHolder.getRequest()); + if (StringUtils.isEmpty(userInfo) || CollectionUtils.isEmpty(userInfo.getPermissions())) { + return false; + } + return hasPermissions(userInfo.getPermissions(), permission); + } + + /** + * 验证用户是否不具备某权限,与 hasPermi逻辑相反 + * + * @param permission 权限字符串 + * @return 用户是否不具备某权限 + */ + public boolean lacksPermi(String permission) { + return hasPermi(permission) != true; + } + + /** + * 验证用户是否具有以下任意一个权限 + * + * @param permissions 权限列表 + * @return 用户是否具有以下任意一个权限 + */ + public boolean hasAnyPermi(String[] permissions) { + LoginUser userInfo = jwtTemplate.getLoginUser(RequestHolder.getRequest()); + if (StringUtils.isEmpty(userInfo) || CollectionUtils.isEmpty(userInfo.getPermissions())) { + return false; + } + Collection authorities = userInfo.getPermissions(); + for (String permission : permissions) { + if (permission != null && hasPermissions(authorities, permission)) { + return true; + } + } + return false; + } + + /** + * 判断用户是否拥有某个角色 + * + * @param role 角色字符串 + * @return 用户是否具备某角色 + */ + public boolean hasRole(String role) { + LoginUser userInfo = jwtTemplate.getLoginUser(RequestHolder.getRequest()); + if (StringUtils.isEmpty(userInfo) || CollectionUtils.isEmpty(userInfo.getRoles())) { + return false; + } + for (String roleKey : userInfo.getRoles()) { + if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(role)) { + return true; + } + } + return false; + } + + /** + * 验证用户是否不具备某角色,与 isRole逻辑相反。 + * + * @param role 角色名称 + * @return 用户是否不具备某角色 + */ + public boolean lacksRole(String role) { + return hasRole(role) != true; + } + + /** + * 验证用户是否具有以下任意一个角色 + * + * @param roles 角色列表 + * @return 用户是否具有以下任意一个角色 + */ + public boolean hasAnyRoles(String[] roles) { + LoginUser userInfo = jwtTemplate.getLoginUser(RequestHolder.getRequest()); + if (StringUtils.isEmpty(userInfo) || CollectionUtils.isEmpty(userInfo.getRoles())) { + return false; + } + for (String role : roles) { + if (hasRole(role)) { + return true; + } + } + return false; + } + + /** + * 判断是否包含权限 + * + * @param authorities 权限列表 + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + private boolean hasPermissions(Collection authorities, String permission) { + return authorities.stream().filter(StringUtils::hasText) + .anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(permission, x)); + } +} diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/consts/HttpStatus.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/consts/HttpStatus.java index b354bfb0b875dba43db6efbf8bb84f12a2ce5291..ec0ce01f544697c0e87eb044981bf0b6319a36b9 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/consts/HttpStatus.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/consts/HttpStatus.java @@ -52,7 +52,7 @@ public class HttpStatus { public static final int UNAUTHORIZED = 401; /** - * 访问受限,授权过期 + * 访问受限,授权不足/过期 */ public static final int FORBIDDEN = 403; diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/GlobalExceptionHandler.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/GlobalExceptionHandler.java index e6f1deeeb1a625fc20cd437bcc8a97718fd899cd..c8e775d91b0afe7af196bb1ec2b3e6ea44dd4492 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/GlobalExceptionHandler.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/GlobalExceptionHandler.java @@ -47,6 +47,14 @@ public class GlobalExceptionHandler { return new ResponseResult(CommonCode.NOTFOUND); } + /** + * 权限异常 + */ + @ExceptionHandler(PreAuthorizeException.class) + public ResponseResult preAuthorizeException(PreAuthorizeException e) { + return new ResponseResult(CommonCode.UNAUTHORISE); + } + //捕获 CustomException异常 @ExceptionHandler(CustomException.class) diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/PreAuthorizeException.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/PreAuthorizeException.java new file mode 100644 index 0000000000000000000000000000000000000000..0afcff1c339940980703bdbd06739fa3edf6a2cb --- /dev/null +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/PreAuthorizeException.java @@ -0,0 +1,12 @@ +package cn.chenc.framework.core.exception; + +/** + * 权限异常 + * + */ +public class PreAuthorizeException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public PreAuthorizeException() { + } +} diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/UtilException.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/UtilException.java index e2b05128354639eff5f8a1037e34f38e262e2a99..46ebea40f0dc0c1cebfb8244d90efc0e9acf433b 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/UtilException.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/UtilException.java @@ -3,7 +3,7 @@ package cn.chenc.framework.core.exception; /** * 工具类异常 * - * @author ruoyi + * @author secret */ public class UtilException extends RuntimeException { private static final long serialVersionUID = 8247610319171014183L; diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/file/FileSizeLimitExceededException.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/file/FileSizeLimitExceededException.java index 7c784396e29d4839605fa8c1a7b8bffa6d4bac2e..4d452e632a60da1fcc31e470f29e3dd8b12fabe2 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/file/FileSizeLimitExceededException.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/file/FileSizeLimitExceededException.java @@ -3,7 +3,7 @@ package cn.chenc.framework.core.exception.file; /** * 文件名大小限制异常类 * - * @author ruoyi + * @author secret */ public class FileSizeLimitExceededException extends FileException { private static final long serialVersionUID = 1L; diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/file/InvalidExtensionException.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/file/InvalidExtensionException.java index 47d40adc1884a35edc836dbe3ef4348f1d2524d5..b264a57bb76d2b6c9301c8923e35512fbc61982c 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/file/InvalidExtensionException.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/exception/file/InvalidExtensionException.java @@ -7,7 +7,7 @@ import java.util.Arrays; /** * 文件上传 误异常类 * - * @author ruoyi + * @author secret */ public class InvalidExtensionException extends FileUploadException { private static final long serialVersionUID = 1L; @@ -58,4 +58,20 @@ public class InvalidExtensionException extends FileUploadException { super(allowedExtension, extension, filename); } } + + public static class InvalidVideoExtensionException extends InvalidExtensionException { + private static final long serialVersionUID = 1L; + + public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename) { + super(allowedExtension, extension, filename); + } + } + + public static class InvalidAudioExtensionException extends InvalidExtensionException { + private static final long serialVersionUID = 1L; + + public InvalidAudioExtensionException(String[] allowedExtension, String extension, String filename) { + super(allowedExtension, extension, filename); + } + } } diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/filter/XssHttpServletRequestWrapper.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/filter/XssHttpServletRequestWrapper.java index 196de28dc3ff143217f42ac3bf83b5b428ec76fe..ba9b39ffd3410e1308ba8f185e341910f391a7d4 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/filter/XssHttpServletRequestWrapper.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/filter/XssHttpServletRequestWrapper.java @@ -87,6 +87,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { */ public boolean isJsonRequest() { String header = super.getHeader(HttpHeaders.CONTENT_TYPE); - return MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(header); + return StringUtils.startsWithIgnoreCase(header,MediaType.APPLICATION_JSON_VALUE); } } diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/model/request/RequestUtil.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/model/request/RequestUtil.java index 09f4aecf5d8b8808b282c00a72eaadef17673ef9..da6153d2b9e6d456fbf849cdb9e3f31a5f9bcb44 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/model/request/RequestUtil.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/model/request/RequestUtil.java @@ -1,7 +1,7 @@ package cn.chenc.framework.core.model.request; -import cn.chenc.framework.core.util.IpUtil; +import cn.chenc.framework.core.util.ip.IpUtils; import javax.servlet.http.HttpServletRequest; import java.util.Enumeration; @@ -88,7 +88,7 @@ public class RequestUtil { if (null == request) { return null; } - return IpUtil.getRealIp(request); + return IpUtils.getIpAddr(request); } /** diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/model/response/CommonCode.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/model/response/CommonCode.java index 0924f50e375a4d21f9e37f0f5e71b03a7ebd5677..2ce48980f3ef55c72162a5b444d7db0c94746345 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/model/response/CommonCode.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/model/response/CommonCode.java @@ -12,12 +12,12 @@ import lombok.ToString; @ToString public enum CommonCode implements ResultCode{ - SUCCESS(true,10000,"操作成功!"), - FAIL(false,11111,"操作失败!"), + SUCCESS(true,200,"操作成功!"), + FAIL(false,500,"操作失败!"), NOTFOUND(false,404,"not found!"), - UNAUTHENTICATED(false,10001,"此操作需要登陆系统!"), - UNAUTHORISE(false,10002,"权限不足,无权操作!"), + UNAUTHORISE(false,403,"权限不足,无权操作!"), SERVER_ERROR(false,99999,"抱歉,系统繁忙,请稍后重试!"); + //操作是否成功 boolean success; //操作代码 diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/IDUtils.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/IDUtils.java deleted file mode 100644 index 6bd2c435fad737a518f6d132beb507f90850f8e3..0000000000000000000000000000000000000000 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/IDUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.chenc.framework.core.util; - -import java.util.Random; - -/** - * 各种id生成策略 - *

Title: IDUtils

- *

Description:

- * @author chenc - * @version 1.0 - */ -public class IDUtils { - - /** - * 图片名生成 - */ - public static String genImageName() { - //取当前时间的长整形值包含毫秒 - long millis = System.currentTimeMillis(); - //long millis = System.nanoTime(); - //加上三位随机数 - Random random = new Random(); - int end3 = random.nextInt(999); - //如果不足三位前面补0 - String str = millis + String.format("%03d", end3); - - return str; - } - - /** - * 普通id生成 - */ - public static long genItemId() { - //取当前时间的长整形值包含毫秒 - long millis = System.currentTimeMillis(); - //long millis = System.nanoTime(); - //加上两位随机数 - Random random = new Random(); - int end2 = random.nextInt(99); - //如果不足两位前面补0 - String str = millis + String.format("%02d", end2); - long id = new Long(str); - return id; - } - -} diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/IpUtil.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/IpUtil.java deleted file mode 100644 index ec7c4adba8e56c69a81dba1f8496a5e5dcd46d41..0000000000000000000000000000000000000000 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/IpUtil.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.chenc.framework.core.util; - -import org.springframework.util.StringUtils; - -import javax.servlet.http.HttpServletRequest; - -/** - * 获取IP的工具类 - * - * @author yadong.zhang (yadong.zhang0415(a)gmail.com) - * @version 1.0 - * @website https://www.zhyd.me - * @date 2018/4/18 11:48 - * @since 1.0 - */ -public class IpUtil { - - /** - * 获取真实IP - * - * @param request - * @return - */ - public static String getRealIp(HttpServletRequest request) { - String ip = request.getHeader("x-forwarded-for"); - return checkIp(ip) ? ip : ( - checkIp(ip = request.getHeader("Proxy-Client-IP")) ? ip : ( - checkIp(ip = request.getHeader("WL-Proxy-Client-IP")) ? ip : - request.getRemoteAddr())); - } - - /** - * 校验IP - * - * @param ip - * @return - */ - private static boolean checkIp(String ip) { - return StringUtils.hasText(ip) && !"unknown".equalsIgnoreCase(ip); - } -} diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/file/FileUploadUtils.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/file/FileUploadUtils.java index 4440476ae195f455e781fb5f33451f06e333fd3e..e37875293412feeae008af6c60116b57389b7483 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/file/FileUploadUtils.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/file/FileUploadUtils.java @@ -22,7 +22,7 @@ public class FileUploadUtils { /** * 默认大小 50M */ - public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024; + public static long defaultMaxSize = 50 * 1024 * 1024; /** * 默认的文件名最大长度 100 @@ -43,6 +43,14 @@ public class FileUploadUtils { return defaultBaseDir; } + public static long getDefaultMaxSize() { + return defaultMaxSize; + } + + public static void setDefaultMaxSize(long defaultMaxSize) { + FileUploadUtils.defaultMaxSize = defaultMaxSize; + } + /** * 以默认配置进行文件上传 * @@ -119,12 +127,10 @@ public class FileUploadUtils { private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException { File desc = new File(uploadDir + File.separator + fileName); - if (!desc.getParentFile().exists()) { - desc.getParentFile().mkdirs(); - } - if (!desc.exists()) - { - desc.createNewFile(); + if (!desc.exists()) { + if (!desc.getParentFile().exists()) { + desc.getParentFile().mkdirs(); + } } return desc; } @@ -147,8 +153,8 @@ public class FileUploadUtils { public static final void assertAllowed(MultipartFile file, String[] allowedExtension) throws FileSizeLimitExceededException, InvalidExtensionException { long size = file.getSize(); - if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE) { - throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); + if (defaultMaxSize != -1 && size > defaultMaxSize) { + throw new FileSizeLimitExceededException(defaultMaxSize / 1024 / 1024); } String fileName = file.getOriginalFilename(); @@ -157,14 +163,18 @@ public class FileUploadUtils { if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) { throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, fileName); - } - else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) { + } else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) { throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, fileName); - } - else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) { + } else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) { throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, fileName); + } else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) { + throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension, + fileName); + } else if (allowedExtension == MimeTypeUtils.AUDIO_EXTENSION) { + throw new InvalidExtensionException.InvalidAudioExtensionException(allowedExtension, extension, + fileName); } else { throw new InvalidExtensionException(allowedExtension, extension, fileName); diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/file/MimeTypeUtils.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/file/MimeTypeUtils.java index 8d745b7cb4a6ff7823d3f7d90bed755340dd82ac..f56ab526128ef95f08c4a0373b7c43af2c486c61 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/file/MimeTypeUtils.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/file/MimeTypeUtils.java @@ -22,9 +22,17 @@ public class MimeTypeUtils { public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", "asf", "rm", "rmvb" }; + public static final String[] VIDEO_EXTENSION = { "mp4", "wmv", "avi", "rmvb" }; + + public static final String[] AUDIO_EXTENSION = {"mp3", "wav", "wma"}; + public static final String[] DEFAULT_ALLOWED_EXTENSION = { // 图片 "bmp", "gif", "jpg", "jpeg", "png", + // 视频格式 + "mp4", "wmv", "avi", "rmvb", + // 音频格式 + "mp3", "wav", "wma", // word excel powerpoint "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", // 压缩文件 diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/html/EscapeUtil.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/html/EscapeUtil.java index df0fc0336b2d1c1266b9efe62b096158e39ae890..669305a79153d34f6f3d270d7c3a356fc2d23534 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/html/EscapeUtil.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/html/EscapeUtil.java @@ -120,14 +120,4 @@ public class EscapeUtil { return tmp.toString(); } -// public static void main(String[] args) { -//// String html = ""; -//// String html = "ipt>alert(\"XSS\")ipt>"; -//// String html = "<123"; -// // String html = "123>"; -// String html = "
qwer
"; -// System.out.println(EscapeUtil.clean(html)); -// System.out.println(EscapeUtil.escape(html)); -// System.out.println(EscapeUtil.unescape(html)); -// } } diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/ip/IpUtils.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/ip/IpUtils.java index 87d22d5bf061ff6e3d37ab62319613bb90b9bca8..cc374aec9d18c03bc7a6e06743d663c12343e943 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/ip/IpUtils.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/ip/IpUtils.java @@ -14,6 +14,11 @@ import java.net.UnknownHostException; */ public class IpUtils { + /** + * 获取ip地址 + * @param request + * @return + */ public static String getIpAddr(HttpServletRequest request) { if (request == null) diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/security/Base64.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/security/Base64.java index ec094db73c42eaf28c294438faa189d8db434e47..06b480cd57b6762aef7bbe6e92b8050892eb9736 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/security/Base64.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/security/Base64.java @@ -3,7 +3,6 @@ package cn.chenc.framework.core.util.security; /** * Base64工具类 * - * @author ruoyi */ public final class Base64 { static private final int BASELENGTH = 128; diff --git a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/security/RsaEncryptUtil.java b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/security/RsaEncryptUtil.java index 97acb8771a915218f1df79168f69ec6fbce6fe5c..4e70afb1dd881172003007026ca766080dc5a92f 100644 --- a/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/security/RsaEncryptUtil.java +++ b/secret-boot-framework-core/src/main/java/cn/chenc/framework/core/util/security/RsaEncryptUtil.java @@ -18,13 +18,13 @@ import java.util.Map; * */ public class RsaEncryptUtil { - private static Map keyMap = new HashMap(); //用于封装随机产生的公钥与私钥 + private static Map keyMap = new HashMap(); //用于封装随机产生的公钥与私钥 // /** * 随机生成密钥对 * @throws NoSuchAlgorithmException */ - public static void genKeyPair() throws NoSuchAlgorithmException { + public static Map genKeyPair() throws NoSuchAlgorithmException { // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); // 初始化密钥对生成器,密钥大小为96-1024位 @@ -37,8 +37,9 @@ public class RsaEncryptUtil { // 得到私钥字符串 String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded()))); // 将公钥和私钥保存到Map - keyMap.put(0,publicKeyString); //0表示公钥 - keyMap.put(1,privateKeyString); //1表示私钥 + keyMap.put("publicKey",publicKeyString); + keyMap.put("privateKey",privateKeyString); + return keyMap; } /** * RSA公钥加密 @@ -51,7 +52,7 @@ public class RsaEncryptUtil { * @throws Exception * 加密过程中的异常信息 */ - public static String encrypt( String str, String publicKey ) throws Exception{ + public static String encryptByPublicKey( String str, String publicKey ) throws Exception{ //base64编码的公钥 byte[] decoded = Base64.decodeBase64(publicKey); RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); @@ -62,6 +63,40 @@ public class RsaEncryptUtil { return outStr; } + /** + * 公钥解密 + * + * @param publicKeyString 公钥 + * @param text 待解密的信息 + * @return 解密后的文本 + */ + public static String decryptByPublicKey(String publicKeyString, String text) throws Exception { + X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString)); + 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 privateKeyString 私钥 + * @param text 待加密的信息 + * @return 加密后的文本 + */ + public static String encryptByPrivateKey(String privateKeyString, String text) throws Exception { + PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString)); + 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); + } + /** * RSA私钥解密 * diff --git a/secret-boot-framework-demo/common-demo/pom.xml b/secret-boot-framework-demo/common-demo/pom.xml index 8e8f7300da24fb6b9547f4e22c1ddc66217fcdfe..4ecb17021ca387616952d2d71eebcd094960adcd 100644 --- a/secret-boot-framework-demo/common-demo/pom.xml +++ b/secret-boot-framework-demo/common-demo/pom.xml @@ -5,11 +5,10 @@ 通用demo - 4.0.0 - + com.gitee.secretopen common-demo - + 1.0-SNAPSHOT @@ -108,6 +107,15 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + org.apache.maven.plugins diff --git a/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/SessionConfig.java b/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/JwtConfig.java similarity index 32% rename from secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/SessionConfig.java rename to secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/JwtConfig.java index 8427ea0c30acdd85c70b818533e6fd7a8b0d9df0..ce68a5673916d7b9a95a09706ec3cf5578375c77 100644 --- a/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/SessionConfig.java +++ b/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/JwtConfig.java @@ -1,15 +1,25 @@ package cn.chenc.framework.demo.config; +import cn.chenc.framework.core.component.JwtTemplate; +import cn.chenc.framework.core.component.RedisJwtTemplate; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; /** *  @description: TODO *  @author secret - *  @date 2021/4/2 15:18 + *  @date 2021/4/28 17:31 * */ @Configuration -@EnableRedisHttpSession -public class SessionConfig { +public class JwtConfig { + + @Bean + public JwtTemplate securityJwtTemplate(){ + JwtTemplate jwtTemplate = new RedisJwtTemplate(); + return jwtTemplate; + } + + + } diff --git a/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/ThreadPoolConfig.java b/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/ThreadPoolConfig.java index 9ebcc114ed24f1d2612ecd62dbebc91d9316e597..7a032eca4940c8a0dbdd89fe2e696a9d755a6304 100644 --- a/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/ThreadPoolConfig.java +++ b/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/ThreadPoolConfig.java @@ -33,7 +33,7 @@ public class ThreadPoolConfig { // 线程池维护线程所允许的空闲时间 private int keepAliveSeconds = 300; - @Bean(name = "threadPoolTaskExecutor") + @Bean(name = {"threadPoolTaskExecutor"}) public ThreadPoolTaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setMaxPoolSize(maxPoolSize); diff --git a/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/WebMvcConfig.java b/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/WebMvcConfig.java index f0a32413ccb91b0e76832181885bb52af67cf64d..225ec12533fcdb2d82eb1d1af90a6d1ef7f199a5 100644 --- a/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/WebMvcConfig.java +++ b/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/config/WebMvcConfig.java @@ -45,6 +45,7 @@ public class WebMvcConfig implements WebMvcConfigurer { .excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**","swagger-ui.html", "/swagger-ui.html/**", + "/static/**", "/css/**", "/data/**", "/images/**", @@ -54,21 +55,12 @@ public class WebMvcConfig implements WebMvcConfigurer { } - - @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/static/**") + registry.addResourceHandler("/**") .addResourceLocations("classpath:/static/"); - registry.addResourceHandler("swagger-ui.html") - .addResourceLocations("classpath:/META-INF/resources/"); - registry.addResourceHandler("/webjars/**") - .addResourceLocations("classpath:/META-INF/resources/webjars/"); - - } - } diff --git a/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/controller/UserController.java b/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/controller/UserController.java index df8146f1e45187b8707015ee972dd5923a371a6b..1a1f97200a5326289fe55395efe3123e5d3bbf2e 100644 --- a/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/controller/UserController.java +++ b/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/controller/UserController.java @@ -1,5 +1,7 @@ package cn.chenc.framework.demo.controller; +import cn.chenc.framework.core.annotation.PreAuthorize; +import cn.chenc.framework.core.model.response.AjaxResult; import cn.chenc.framework.core.model.response.ResponseVO; import cn.chenc.framework.core.model.response.ResultUtil; import cn.chenc.framework.demo.entity.User; @@ -65,5 +67,11 @@ public class UserController { return ResultUtil.success(user); } + @PreAuthorize(hasPermi = "test") + @GetMapping("/testPermission") + public AjaxResult testPermission(){ + return AjaxResult.success(); + } + } diff --git a/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/entity/User.java b/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/entity/User.java index 0573f1311c61cdb4e3fade9946639d2e1c6e3e64..eca74d95141515a3c9807b3e3d12e5581df940fa 100644 --- a/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/entity/User.java +++ b/secret-boot-framework-demo/common-demo/src/main/java/cn/chenc/framework/demo/entity/User.java @@ -1,6 +1,6 @@ package cn.chenc.framework.demo.entity; -import cn.chenc.framework.mybatisplus.model.BaseConditionVO; +import cn.chenc.framework.mybatisplus.model.BaseEntity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -17,7 +17,7 @@ import java.util.Date; * */ @TableName("user") -public class User extends BaseConditionVO implements Serializable { +public class User extends BaseEntity implements Serializable { private static final long serialVersionUID = 1L; diff --git a/secret-boot-framework-demo/jpa-demo/pom.xml b/secret-boot-framework-demo/jpa-demo/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..3c5319a524eddd3d16cdfda4602e3c2064ee3aba --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/pom.xml @@ -0,0 +1,126 @@ + + + 4.0.0 + + com.gitee.secretopen + jpa-demo + 1.0-SNAPSHOT + + + + + com.gitee.secretopen + secret-boot-framework-dependencies + 1.5.0 + pom + import + + + + + + + com.gitee.secretopen + secret-boot-framework-core + + + com.gitee.secretopen + secret-boot-framework-jpa + + + + + + + dev + + true + + + dev + + + + ${project.artifactId}-${project.version} + + + + + test + + test + + + + ${project.artifactId} + + + + + prod + + prod + + + + ${project.artifactId} + + + + + + + + + src/main/resources + + application*.yml + + + + src/main/resources + + true + + application.yml + application-${profileActive}.yml + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + @ + + false + + + + org.springframework.boot + spring-boot-maven-plugin + + cn.chenc.framework.demo.CommonDemoApplication + JAR + + false + + + + + + diff --git a/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/JpaDemoApplication.java b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/JpaDemoApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..4a2a097adf37bc00923a1ac0944d5128475d61c7 --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/JpaDemoApplication.java @@ -0,0 +1,21 @@ +package cn.chenc.framework.demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + *  @description: TODO + *  @author secret + *  @date 2021/5/14 14:07 + * + */ +@SpringBootApplication +@EnableTransactionManagement +public class JpaDemoApplication { + + public static void main(String[] args){ + SpringApplication.run(JpaDemoApplication.class, args); + } + +} diff --git a/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/controller/UserController.java b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/controller/UserController.java new file mode 100644 index 0000000000000000000000000000000000000000..37a423ee92c5c76b0aac7586e3b1f1b8e2386e56 --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/controller/UserController.java @@ -0,0 +1,41 @@ +package cn.chenc.framework.demo.controller; + +import cn.chenc.framework.core.model.response.AjaxResult; +import cn.chenc.framework.demo.entity.UserEntity; +import cn.chenc.framework.demo.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + *  @description: TODO + *  @author secret + *  @date 2021/5/14 16:04 + * + */ +@RestController +@RequestMapping("/user") +public class UserController { + + @Autowired + private UserService userService; + + @GetMapping("/all") + public List queryAll() { + return userService.queryAll(); + } + + @GetMapping("/list") + public Page queryUserPageList(UserEntity userEntity){ + return userService.queryUserPageList(userEntity); + } + + @PostMapping + public AjaxResult insertUser(@RequestBody UserEntity userEntity){ + userService.insertUser(userEntity); + return AjaxResult.success(); + } + +} diff --git a/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/dao/UserRepository.java b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/dao/UserRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..756c3baf146bb1a78db989d947a9f6cf93a32562 --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/dao/UserRepository.java @@ -0,0 +1,17 @@ +package cn.chenc.framework.demo.dao; + +import cn.chenc.framework.demo.entity.UserEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +/** + *  @description: TODO + *  @author secret + *  @date 2021/5/14 15:26 + * + */ +public interface UserRepository extends JpaRepository, JpaSpecificationExecutor { + + + +} diff --git a/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/entity/UserEntity.java b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/entity/UserEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..594090d1b5c9dec6dc6d89b72ca762ff06ef6187 --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/entity/UserEntity.java @@ -0,0 +1,92 @@ +package cn.chenc.framework.demo.entity; + +import cn.chenc.framework.jpa.model.BaseEntity; + +import javax.persistence.*; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *  @description: TODO + *  @author secret + *  @date 2021/5/14 14:51 + * + */ +@Entity +@Table(name = "user", schema = "secret_framework") +public class UserEntity extends BaseEntity implements Serializable { + + @Id + @Column(name = "id", nullable = false) + private Integer id; + + @Basic + @Column(name = "username", nullable = true, length = 255) + private String username; + + @Basic + @Column(name = "sex", nullable = true) + private Integer sex; + + @Basic + @Column(name = "birthday", nullable = true) + private LocalDateTime birthday; + + @Basic + @Column(name = "phone", nullable = true, length = 255) + private String phone; + + @Basic + @Column(name = "email", nullable = true, length = 255) + private String email; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public Integer getSex() { + return sex; + } + + public void setSex(Integer sex) { + this.sex = sex; + } + + public LocalDateTime getBirthday() { + return birthday; + } + + public void setBirthday(LocalDateTime birthday) { + this.birthday = birthday; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + +} diff --git a/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/service/UserService.java b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/service/UserService.java new file mode 100644 index 0000000000000000000000000000000000000000..d734cffe5fee833044d1df838fd2d8ea45627a54 --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/service/UserService.java @@ -0,0 +1,21 @@ +package cn.chenc.framework.demo.service; + +import cn.chenc.framework.demo.entity.UserEntity; +import org.springframework.data.domain.Page; + +import java.util.List; + +/** + *  @description: TODO + *  @author secret + *  @date 2021/5/14 15:45 + * + */ +public interface UserService { + + List queryAll(); + + Page queryUserPageList(UserEntity userEntity); + + void insertUser(UserEntity userEntity); +} diff --git a/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/service/impl/UserServiceImpl.java b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/service/impl/UserServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..ea759bc060c12cbda431a646257e1549d6a7b530 --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/src/main/java/cn/chenc/framework/demo/service/impl/UserServiceImpl.java @@ -0,0 +1,63 @@ +package cn.chenc.framework.demo.service.impl; + +import cn.chenc.framework.core.util.StringUtils; +import cn.chenc.framework.demo.dao.UserRepository; +import cn.chenc.framework.demo.entity.UserEntity; +import cn.chenc.framework.demo.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import java.util.ArrayList; +import java.util.List; + +/** + *  @description: TODO + *  @author secret + *  @date 2021/5/14 15:47 + * + */ +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserRepository userRepository; + + @Override + public List queryAll() { + return userRepository.findAll(); + } + + @Override + public Page queryUserPageList(UserEntity userEntity) { + Pageable pageable = PageRequest.of(userEntity.getPageIndex()-1, userEntity.getPageSize()); + Specification specification=new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + List predicates = new ArrayList<>(); + if(StringUtils.isNotEmpty(userEntity.getUsername())){ + Predicate predicate = criteriaBuilder.equal(root.get("username").as(String.class),userEntity.getUsername()); + predicates.add(predicate); + } + Predicate[] pre = predicates.toArray(new Predicate[predicates.size()]); + return criteriaQuery.where(pre).getRestriction(); + } + }; + return userRepository.findAll(specification,pageable); + } + + @Override + @Transactional + public void insertUser(UserEntity userEntity) { + userRepository.save(userEntity); + } + +} diff --git a/secret-boot-framework-demo/jpa-demo/src/main/resources/application-dev.yml b/secret-boot-framework-demo/jpa-demo/src/main/resources/application-dev.yml new file mode 100644 index 0000000000000000000000000000000000000000..7b7de87fbed7d2d25ddecb8b3859858eeba381d7 --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/src/main/resources/application-dev.yml @@ -0,0 +1,60 @@ +# Server settings +server: + port: 8080 + servlet: + context-path: / +spring: + datasource: + druid: + connection-init-sqls: set names utf8mb4 + driver-class-name: com.mysql.cj.jdbc.Driver + initial-size: 5 + min-idle: 5 + max-active: 20 + # 配置获取连接等待超时的时间 + max-wait: 180000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + time-between-eviction-runs-millis: 180000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + min-evictable-idle-time-millis: 300000 + test-while-idle: true + test-on-borrow: false + test-on-return: false + type: com.alibaba.druid.pool.DruidDataSource + url: jdbc:mysql://127.0.0.1:3306/secret_framework?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT&rewriteBatchedStatements=true + username: root + password: 111111 + # Redis数据库索引(默认为0) + redis: + jedis: + pool: + # 连接池最大连接数(使用负值表示没有限制) + max-active: 8 + # 连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接超时时间(毫秒) + timeout: 5000ms + # 默认的数据过期时间 + expire: 2592000 + jpa: + properties: + hibernate: + hbm2ddl: + auto: update + dialect: org.hibernate.dialect.MySQL5InnoDBDialect + format_sql: true + show-sql: true + +#日志 +logging: + level: + root: info + org.hibernate.type.descriptor.sql.BasicBinder: trace +# org.springframework.scheduling: INFO + +####################################自定义配置########################################## + diff --git a/secret-boot-framework-demo/jpa-demo/src/main/resources/application-prod.yml b/secret-boot-framework-demo/jpa-demo/src/main/resources/application-prod.yml new file mode 100644 index 0000000000000000000000000000000000000000..058d19ed3478ad714af8ba8bea679974e7d50898 --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/src/main/resources/application-prod.yml @@ -0,0 +1,50 @@ +# Server settings +server: + port: 8080 + servlet: + context-path: / +spring: + datasource: + druid: + connection-init-sqls: set names utf8mb4 + driver-class-name: com.mysql.jdbc.Driver + initial-size: 5 + min-idle: 5 + max-active: 20 + # 配置获取连接等待超时的时间 + max-wait: 180000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + time-between-eviction-runs-millis: 180000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + min-evictable-idle-time-millis: 300000 + test-while-idle: true + test-on-borrow: false + test-on-return: false + type: com.alibaba.druid.pool.DruidDataSource + url: jdbc:mysql://127.0.0.1:3306/metadata?useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true + username: root + password: 111111 + # Redis数据库索引(默认为0) + redis: + jedis: + pool: + # 连接池最大连接数(使用负值表示没有限制) + max-active: 8 + # 连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接超时时间(毫秒) + timeout: 5000ms + # 默认的数据过期时间,主要用于shiro权限管理 + expire: 2592000 + +#日志 +logging: + level: + root: info + +####################################自定义配置########################################## + diff --git a/secret-boot-framework-demo/jpa-demo/src/main/resources/application-test.yml b/secret-boot-framework-demo/jpa-demo/src/main/resources/application-test.yml new file mode 100644 index 0000000000000000000000000000000000000000..058d19ed3478ad714af8ba8bea679974e7d50898 --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/src/main/resources/application-test.yml @@ -0,0 +1,50 @@ +# Server settings +server: + port: 8080 + servlet: + context-path: / +spring: + datasource: + druid: + connection-init-sqls: set names utf8mb4 + driver-class-name: com.mysql.jdbc.Driver + initial-size: 5 + min-idle: 5 + max-active: 20 + # 配置获取连接等待超时的时间 + max-wait: 180000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + time-between-eviction-runs-millis: 180000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + min-evictable-idle-time-millis: 300000 + test-while-idle: true + test-on-borrow: false + test-on-return: false + type: com.alibaba.druid.pool.DruidDataSource + url: jdbc:mysql://127.0.0.1:3306/metadata?useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true + username: root + password: 111111 + # Redis数据库索引(默认为0) + redis: + jedis: + pool: + # 连接池最大连接数(使用负值表示没有限制) + max-active: 8 + # 连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接超时时间(毫秒) + timeout: 5000ms + # 默认的数据过期时间,主要用于shiro权限管理 + expire: 2592000 + +#日志 +logging: + level: + root: info + +####################################自定义配置########################################## + diff --git a/secret-boot-framework-demo/jpa-demo/src/main/resources/application.yml b/secret-boot-framework-demo/jpa-demo/src/main/resources/application.yml new file mode 100644 index 0000000000000000000000000000000000000000..ef5e12ad03217802c468dee8a6759df6fb8851f9 --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/src/main/resources/application.yml @@ -0,0 +1,32 @@ +# Server settings +server: + # HTTP请求和响应头的最大量,以字节为单位,默认值为4096字节,超过此长度的部分不予处理,一般8K。解决java.io.EOFException: null问题 + max-http-header-size: 8192 + compression: + enabled: true + min-response-size: 1024 + mime-types: text/plain,text/css,text/xml,text/javascript,application/json,application/javascript,application/xml,application/xml+rss,application/x-javascript,application/x-httpd-php,image/jpeg,image/gif,image/png + tomcat: + uri-encoding: UTF-8 + remoteip: + remote-ip-header: X-Forwarded-for + protocol-header: X-Forwarded-Proto + remote: + port-header: X-Forwarded-Port + forward-headers-strategy: native +spring: + main: + allow-bean-definition-overriding: false + application: + name: secret-boot-framework-demo +# mvc: +# throw-exception-if-no-handler-found: true +# web: +# resources: +# add-mappings: false + profiles: + active: '@profileActive@' +#日志 +logging: + file: + path: ./logs diff --git a/secret-boot-framework-demo/jpa-demo/src/main/resources/logback-spring.xml b/secret-boot-framework-demo/jpa-demo/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000000000000000000000000000000000..f8c21c4fc830db1d562ef56d70a98aa47f5db56f --- /dev/null +++ b/secret-boot-framework-demo/jpa-demo/src/main/resources/logback-spring.xml @@ -0,0 +1,199 @@ + + + + + + + + + + logback + + + + + + + + + + + + + + + + + trace + + + ${CONSOLE_LOG_PATTERN} + + UTF-8 + + + + + + + + + + ${log.path}/log_debug.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + ${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + + + + debug + ACCEPT + DENY + + + + + + + ${log.path}/log_info.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + ${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + + + + info + ACCEPT + DENY + + + + + + + ${log.path}/log_warn.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + ${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + + + + warn + ACCEPT + DENY + + + + + + + + ${log.path}/log_error.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + ${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/secret-boot-framework-demo/pom.xml b/secret-boot-framework-demo/pom.xml deleted file mode 100644 index 9fe0ec35a0f1be788a6ef795d10fd909e921da2e..0000000000000000000000000000000000000000 --- a/secret-boot-framework-demo/pom.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - 4.0.0 - - secret-boot-framework-demo - - demo案例 - - diff --git a/secret-boot-framework-demo/security-demo/pom.xml b/secret-boot-framework-demo/security-demo/pom.xml index 9964448d6808c1b0caa9288f37351e6a06e2154d..be2a508da1e7dee816e7bf031fd8081bb0dd1794 100644 --- a/secret-boot-framework-demo/security-demo/pom.xml +++ b/secret-boot-framework-demo/security-demo/pom.xml @@ -4,6 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + security-demo com.gitee.secretopen security-demo 1.0-SNAPSHOT diff --git a/secret-boot-framework-demo/security-demo/src/main/java/cn/chenc/framework/demo/controller/LoginController.java b/secret-boot-framework-demo/security-demo/src/main/java/cn/chenc/framework/demo/controller/LoginController.java index 453a2fb71062409dbaa88102b30b6fc4eb2c2ff0..4703a18ff9d5441f137815a499da72c05935ace6 100644 --- a/secret-boot-framework-demo/security-demo/src/main/java/cn/chenc/framework/demo/controller/LoginController.java +++ b/secret-boot-framework-demo/security-demo/src/main/java/cn/chenc/framework/demo/controller/LoginController.java @@ -9,10 +9,12 @@ import cn.chenc.framework.demo.entity.User; import cn.chenc.framework.security.jwt.SecurityJwtTemplate; import cn.chenc.framework.security.model.LoginUser; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseBody; @@ -59,4 +61,10 @@ public class LoginController { return AjaxResult.success(loginUser); } + @PreAuthorize("@ss.hasPermi('test')") + @GetMapping("/test") + public AjaxResult testPermission(){ + return AjaxResult.success(); + } + } diff --git a/secret-boot-framework-demo/shiro-demo/src/main/java/cn/chenc/framework/demo/controller/LoginController.java b/secret-boot-framework-demo/shiro-demo/src/main/java/cn/chenc/framework/demo/controller/LoginController.java index 3805bdac2e57660950be7c2dd35f4908694a5483..403dbcb1e25615952e77c3d9235c93b9a9ec0687 100644 --- a/secret-boot-framework-demo/shiro-demo/src/main/java/cn/chenc/framework/demo/controller/LoginController.java +++ b/secret-boot-framework-demo/shiro-demo/src/main/java/cn/chenc/framework/demo/controller/LoginController.java @@ -73,4 +73,11 @@ public class LoginController { return AjaxResult.success(); } + @ResponseBody + @GetMapping("/exception") + public AjaxResult exception() throws Exception{ + throw new Exception(); + } + + } diff --git a/secret-boot-framework-dependencies/pom.xml b/secret-boot-framework-dependencies/pom.xml index a54daf729b4a3241866431f3666100767546598c..bf1aadacb0b491e4e80de60529c910b482305d8a 100644 --- a/secret-boot-framework-dependencies/pom.xml +++ b/secret-boot-framework-dependencies/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.4.3 + 2.4.5 4.0.0 @@ -15,35 +15,43 @@ pom secret-boot-framework-dependencies + secret-boot-framework-dependencies + https://gitee.com/SecretOpen/secret-boot-framework + 1.8 1.5.0 2.4.3.RELEASE - 1.1.21 - 8.0.16 + 1.2.6 + 8.0.25 2.8.0 1.4 1.9 3.8.0 - 1.10.9 + 1.10.10 4.5.13 4.9.1 - 1.18.16 + 1.18.20 3.0.0 - 30.1-jre + 30.1.1-jre 3.4.2 1.13.1 1.21 - 1.0.0-alpha 0.62.2 - 5.5.9 - 2.2.6 + 5.6.5 + 2.2.9 0.9.1 1.7.1 + + 3.15.4 + + 3.2.1 + 2.9.1 + 1.6 @@ -121,12 +129,6 @@ okhttp ${okhttp.version} - - - me.zhyd.braum.spring.boot - braum-spring-boot-starter - ${braum.version} - commons-fileupload @@ -240,7 +242,132 @@ shiro-spring ${shiro.version} + + + org.redisson + redisson-spring-boot-starter + ${redisson.version} + + + + Apache License, Version 2.0 + https://www.apache.org/licenses/LICENSE-2.0.txt + + + + + scm:git@gitee.com:SecretOpen/secret-boot-framework.git + scm:git@gitee.com:SecretOpen/secret-boot-framework.git + git@gitee.com:SecretOpen/secret-boot-framework.git + + + + + secretC + 1029693356@qq.com + https://gitee.com/SecretOpen + + + + + + + + release + + + + + org.apache.maven.plugins + maven-source-plugin + ${maven-source-plugin.version} + + + package + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven-javadoc-plugin.version} + + -Xdoclint:none + + + + package + + jar + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + ${maven-gpg-plugin.version} + + + + verify + + sign + + + + + + + + + + sonatype + https://oss.sonatype.org/content/repositories/snapshots + + + + sonatype + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + true + + + + + + + ${project.artifactId} + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + UTF-8 + + + + + diff --git a/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/config/CustomerDefaultConverterLoader.java b/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/config/CustomerDefaultConverterLoader.java index df7bccf26f800c516f05d05db795fd63db59115a..80d562b694d67faad52b5d1f0672a502c7aa6567 100644 --- a/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/config/CustomerDefaultConverterLoader.java +++ b/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/config/CustomerDefaultConverterLoader.java @@ -89,7 +89,7 @@ public class CustomerDefaultConverterLoader { private void setConverter(DefaultConverterLoader converters, Field field) throws IllegalAccessException { if (WRITE_CONVERTER.equalsIgnoreCase(field.getName())) { Map map = new HashMap<>(32); - //我的LocalDateTimeConverter + //我们扩展的自定义转化器 putWriteConverter(map, new LocalDateTimeConverter()); putAllConverter(map,new NumberToLocalDateTimeConverter()); //以下jar包自带的Converter @@ -111,7 +111,7 @@ public class CustomerDefaultConverterLoader { field.set(converters, map); } else if (ALL_CONVERTER.equalsIgnoreCase(field.getName())) { Map map = new HashMap<>(64); - //我的LocalDateTimeConverter + //我们扩展的自定义转化器 putAllConverter(map, new LocalDateTimeConverter()); putAllConverter(map,new NumberToLocalDateTimeConverter()); //以下jar包自带的Converter diff --git a/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/converters/LocalDateTimeConverter.java b/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/converters/LocalDateTimeConverter.java index b817bd9a9e8eb8ea9ad6fd8b0fee8b6b7f723e26..5d360a4163994b44f6cf5d5537499d7dd0ceab05 100644 --- a/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/converters/LocalDateTimeConverter.java +++ b/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/converters/LocalDateTimeConverter.java @@ -14,7 +14,7 @@ import java.time.format.DateTimeFormatter; import java.util.Objects; /** - *  @description: TODO + *  @description: 自定义转化器,将String转化为LocalDateTime *  @author 陈_C *  @date 2020/8/26 16:32 * diff --git a/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/converters/NumberToLocalDateTimeConverter.java b/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/converters/NumberToLocalDateTimeConverter.java index b342f156bf4021b9cb31bfa8c71f87e273f701a2..e587381d0773dd437ab13dc2110134d11ec2c68a 100644 --- a/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/converters/NumberToLocalDateTimeConverter.java +++ b/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/converters/NumberToLocalDateTimeConverter.java @@ -18,7 +18,7 @@ import java.util.GregorianCalendar; import java.util.Objects; /** - *  @description: TODO + *  @description: 自定义转化器,将Number转化为LocalDateTime *  @author 陈_C *  @date 2020/8/26 16:32 * @@ -59,7 +59,7 @@ public class NumberToLocalDateTimeConverter implements Converter DateTimeFormat annotation = contentProperty.getField().getAnnotation(DateTimeFormat.class); // LocalDate localDate = LocalDate.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern(Objects.nonNull(annotation) ? annotation.value() : READ_PATTERN)); // LocalDateTime localDateTime = localDate.atStartOfDay(); - + //excel中日期是从1900/00/00开始,日期类型数据格式实际上是与1900/00/00之间的天数差 Calendar calendar = new GregorianCalendar(1900,0,0); Date gregorianDate = calendar.getTime(); String formatExcelDate = DateUtils.format(DateUtils.addDay(gregorianDate, Integer.parseInt(cellData.getNumberValue().toString())), DateUtils.YYYYMMDD); diff --git a/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/listener/ExcelListener.java b/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/listener/ExcelListener.java index 35b24e9f0df574a07521b3b96c5cf4540a2d5115..4bddb5b4e0d106116f155d060abaeee648fe7bf4 100644 --- a/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/listener/ExcelListener.java +++ b/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/listener/ExcelListener.java @@ -2,6 +2,7 @@ package cn.chenc.framework.excel.listener; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; +import org.apache.poi.ss.formula.functions.T; import java.util.ArrayList; import java.util.List; @@ -15,14 +16,31 @@ import java.util.List; public class ExcelListener extends AnalysisEventListener { //可以通过实例获取该值 private List datas = new ArrayList(); + //读取最大行数,默认10万行 + private Integer maxRows = 100000; + + public ExcelListener() { + } + + public ExcelListener(Integer maxRows) { + this.maxRows = maxRows; + } + + public Integer getMaxRows() { + return maxRows; + } + + public void setMaxRows(Integer maxRows) { + this.maxRows = maxRows; + } @Override public void invoke(Object o, AnalysisContext analysisContext) { /** * 数据量超过一定量后存储数据库,防止过多数据在内存,容易OOM */ - if (datas.size()< 1000) { - datas.add(o);//数据存储到list,供批量处理,或后续自己业务逻辑处理。 + if (datas.size()< maxRows) { + datas.add((T) o);//数据存储到list,供批量处理,或后续自己业务逻辑处理。 doSomething(o);//根据自己业务做处理 } } @@ -31,8 +49,8 @@ public class ExcelListener extends AnalysisEventListener { //1、入库调用接口 } - public List getDatas() { - return datas; + public List getDatas() { + return (List) datas; } public void setDatas(List datas) { diff --git a/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/util/EasyExcelUtil.java b/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/util/EasyExcelUtil.java index f78bd2f2d1bdc02d905a46f315a5a6cad042fd7e..5594060e9cef6e322a8c61c46a0fe2e2126dd613 100644 --- a/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/util/EasyExcelUtil.java +++ b/secret-boot-framework-excel/src/main/java/cn/chenc/framework/excel/util/EasyExcelUtil.java @@ -7,10 +7,10 @@ import com.alibaba.excel.ExcelReader; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.write.metadata.WriteSheet; -import org.apache.poi.ss.formula.functions.T; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; @@ -24,9 +24,12 @@ import java.util.List; */ public class EasyExcelUtil { + //写入一个sheet最多100万数据 + private static final Integer MAX_ROWS_ONE_SHEET=1000000; + //excel导出 /** - * @description: excel导出 + * @description: 数据导入excel文件 * @param response * @param listdata 导出数据 * @param filename 导出文件名称 @@ -37,7 +40,25 @@ public class EasyExcelUtil { * @date 2020/8/21 陈_C */ @SuppressWarnings({ "rawtypes", "unchecked" }) - public static void toExcle(HttpServletResponse response, List listdata, String filename, Class clazz) { + public static void toExcle(HttpServletResponse response, List listdata, String filename, Class clazz) { + toExcle(response,listdata,filename,filename,clazz); + } + + /** + * @description: 数据导入excel文件 + * @param response + * @param listdata 导出数据 + * @param filename 导出文件名称 + * @param sheetName 导出sheet名称 + * @param clazz 导出的数据模型 + * @return void + * @throws + * @author 陈_C + * @date 2020/8/21 陈_C + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static void toExcle(HttpServletResponse response, List listdata, String filename,String sheetName, Class clazz) { + ExcelWriter excelWriter= null; try { //设置响应格式 response.setContentType("application/vnd.ms-excel"); @@ -48,56 +69,345 @@ public class EasyExcelUtil { //获取输出流 ServletOutputStream outputStream= response.getOutputStream(); - //获取工作簿对象 - ExcelWriter excelWriter = EasyExcel.write(outputStream, clazz).registerWriteHandler(new CustomCellWriteHandler()).build(); + excelWriter = EasyExcel.write(outputStream, clazz).registerWriteHandler(new CustomCellWriteHandler()).build(); + //获取工作表数量 + Integer sheetnum=getSheetNum(listdata); + //调用写入sheet + writeSheet(excelWriter,listdata,sheetnum,sheetName); + } catch (IOException e) { + e.printStackTrace(); + } finally { + //finish 会帮忙关闭流 + if(excelWriter!=null) { + excelWriter.finish(); + } + } + } + /** + * @description: 数据导入excel文件 + * @param listdata + * @param pathName 文件路径 + * @param sheetName sheet名字 + * @param clazz + * @return void + * @throws + * @author secret + * @date 2021/5/13 secret + */ + public static void toExcle(List listdata, String pathName,String sheetName, Class clazz){ + ExcelWriter excelWriter = null; + try { + //获取工作簿对象 + excelWriter = EasyExcel.write(pathName, clazz).registerWriteHandler(new CustomCellWriteHandler()).build(); //获取工作表数量 - Integer sheetnum=1; - if ( listdata.size()<1000000) { - sheetnum=1; - }else { - sheetnum=listdata.size()%1000000==0 ? listdata.size()/1000000 :listdata.size()/1000000+1;//这里我是根据自身工作需要设置每一百万条数据一个sheet + Integer sheetnum = getSheetNum(listdata); + //调用写入sheet + writeSheet(excelWriter,listdata,sheetnum,sheetName); + } catch (Exception e){ + e.printStackTrace(); + } finally { + //finish 会帮忙关闭流 + if(excelWriter!=null) { + excelWriter.finish(); } + } + } - // 去调用写入,这里我调用了sheetnum次,实际使用时根据数据库分页的总的页数来。这里最终会写到sheetnum个sheet里面 - List subList =null; - for (int i = 0; i < sheetnum; i++) { - // 每次都要创建writeSheet 这里注意必须指定sheetNo - WriteSheet writeSheet = EasyExcel.writerSheet(i,filename+"("+i+")").build(); - //这里是将查询的数据分为若干个sheet页 - subList = listdata.subList(i*1000000,i==sheetnum-1 ? listdata.size() : (i+1)*1000000); - excelWriter.write(subList, writeSheet); + /** + * @description: 数据导入excel文件 + * @param listdata + * @param file 写入文件 + * @param sheetName sheet名字 + * @param clazz + * @return void + * @throws + * @author secret + * @date 2021/5/13 secret + */ + public static void toExcle(List listdata, File file, String sheetName, Class clazz){ + ExcelWriter excelWriter = null; + try { + //获取工作簿对象 + excelWriter = EasyExcel.write(file, clazz).registerWriteHandler(new CustomCellWriteHandler()).build(); + //获取工作表数量 + Integer sheetnum = getSheetNum(listdata); + //调用写入sheet + writeSheet(excelWriter,listdata,sheetnum,sheetName); + } catch (Exception e){ + e.printStackTrace(); + } finally { + //finish 会帮忙关闭流 + if(excelWriter!=null) { + excelWriter.finish(); } + } + } + /** + * @description: excel读取 + * @param pathName + * @param clazz + * @return java.util.List + * @throws + * @author secret + * @date 2021/2/27 secret + */ + public static List readExcel(String pathName, Class clazz){ + return readExcel(pathName,0,clazz); + } - //finish 会帮忙关闭流 - excelWriter.finish(); + /** + * @description: excel读取 + * @param pathName + * @param sheetNo + * @param clazz + * @return java.util.List + * @throws + * @author secret + * @date 2021/2/27 secret + */ + public static List readExcel(String pathName, Integer sheetNo, Class clazz){ + ExcelListener listener = new ExcelListener(); + return readExcel(pathName,sheetNo,clazz,listener); + } - } catch (IOException e) { + /** + * @description: excel读取 + * @param pathName 文件路径 + * @param clazz + * @param maxRows 最大读取行数 + * @return java.util.List + * @throws + * @author secret + * @date 2021/5/13 secret + */ + public static List readExcel(String pathName, Class clazz, Integer maxRows){ + return readExcel(pathName,0,clazz,maxRows); + } - e.printStackTrace(); - } + /** + * excel读取 + * @param pathName 文件路径 + * @param sheetNo + * @param clazz + * @param maxRows + * @return + */ + public static List readExcel(String pathName, Integer sheetNo, Class clazz, Integer maxRows){ + ExcelListener listener = new ExcelListener(maxRows); + return readExcel(pathName,sheetNo,clazz,listener); + } + + + /** + * @description: excel读取 + * @param pathName 文件路径 + * @param sheetNo 读取指定sheet编号 + * @param clazz + * @param listener 读取监听器 + * @return java.util.List + * @throws + * @author secret + * @date 2021/5/13 secret + */ + public static List readExcel(String pathName, Integer sheetNo, Class clazz, ExcelListener listener){ + ExcelReader excelReader=EasyExcel.read(pathName, clazz,listener).build(); + ReadSheet readSheet = EasyExcel.readSheet(sheetNo).build(); + excelReader.read(readSheet); + //获取数据 + List list = listener.getDatas(); + return list; + } + + /** + * @description: excel读取 + * @param file + * @param clazz + * @return java.util.List + * @throws + * @author secret + * @date 2021/2/27 secret + */ + public static List readExcel(File file, Class clazz){ + return readExcel(file,0,clazz); + } + + /** + * @description: excel读取 + * @param file + * @param sheetNo + * @param clazz + * @return java.util.List + * @throws + * @author secret + * @date 2021/2/27 secret + */ + public static List readExcel(File file, Integer sheetNo, Class clazz){ + ExcelListener listener = new ExcelListener(); + return readExcel(file,sheetNo,clazz,listener); + } + + /** + * @description: excel读取 + * @param file + * @param clazz + * @param maxRows 最大读取行数 + * @return java.util.List + * @throws + * @author secret + * @date 2021/5/13 secret + */ + public static List readExcel(File file, Class clazz, Integer maxRows){ + return readExcel(file,0,clazz,maxRows); + } + + /** + * excel读取 + * @param file + * @param sheetNo + * @param clazz + * @param maxRows + * @return + */ + public static List readExcel(File file, Integer sheetNo, Class clazz, Integer maxRows){ + ExcelListener listener = new ExcelListener(maxRows); + return readExcel(file,sheetNo,clazz,listener); + } + + + /** + * @description: excel读取 + * @param file + * @param sheetNo 读取指定sheet编号 + * @param clazz + * @param listener 读取监听器 + * @return java.util.List + * @throws + * @author secret + * @date 2021/5/13 secret + */ + public static List readExcel(File file, Integer sheetNo, Class clazz, ExcelListener listener){ + ExcelReader excelReader=EasyExcel.read(file, clazz,listener).build(); + ReadSheet readSheet = EasyExcel.readSheet(sheetNo).build(); + excelReader.read(readSheet); + //获取数据 + List list = listener.getDatas(); + return list; + } + + /** + * @description: excel读取 + * @param inputStream + * @param clazz + * @return java.util.List + * @throws + * @author secret + * @date 2021/2/27 secret + */ + public static List readExcel(InputStream inputStream, Class clazz){ + return readExcel(inputStream,0,clazz); } /** * @description: excel读取 * @param inputStream + * @param sheetNo * @param clazz * @return java.util.List * @throws * @author secret * @date 2021/2/27 secret */ - public static List readExcel(InputStream inputStream,Class clazz){ + public static List readExcel(InputStream inputStream, Integer sheetNo, Class clazz){ ExcelListener listener = new ExcelListener(); - ExcelReader excelReader=EasyExcel.read(inputStream, clazz,listener ).build(); - ReadSheet readSheet = EasyExcel.readSheet(0).build(); + return readExcel(inputStream,sheetNo,clazz,listener); + } + + /** + * @description: excel读取 + * @param inputStream + * @param clazz + * @param maxRows 最大读取行数 + * @return java.util.List + * @throws + * @author secret + * @date 2021/5/13 secret + */ + public static List readExcel(InputStream inputStream, Class clazz, Integer maxRows){ + return readExcel(inputStream,0,clazz,maxRows); + } + + /** + * excel读取 + * @param inputStream + * @param sheetNo + * @param clazz + * @param maxRows + * @return + */ + public static List readExcel(InputStream inputStream, Integer sheetNo, Class clazz, Integer maxRows){ + ExcelListener listener = new ExcelListener(maxRows); + return readExcel(inputStream,sheetNo,clazz,listener); + } + + + /** + * @description: excel读取 + * @param inputStream + * @param sheetNo 读取指定sheet编号 + * @param clazz + * @param listener 读取监听器 + * @return java.util.List + * @throws + * @author secret + * @date 2021/5/13 secret + */ + public static List readExcel(InputStream inputStream, Integer sheetNo, Class clazz, ExcelListener listener){ + ExcelReader excelReader=EasyExcel.read(inputStream, clazz,listener).build(); + ReadSheet readSheet = EasyExcel.readSheet(sheetNo).build(); excelReader.read(readSheet); //获取数据 - List list = listener.getDatas(); + List list = listener.getDatas(); return list; } + /** + * 计算Sheet数量 + * @param listdata + * @return + */ + private static Integer getSheetNum(List listdata){ + if (listdata.size() listdata,Integer sheetNum,String sheetName){ + // 去调用写入,这里我调用了sheetnum次,实际使用时根据数据库分页的总的页数来。这里最终会写到sheetnum个sheet里面 + List subList = null; + for (int i = 0; i < sheetNum; i++) { + // 每次都要创建writeSheet 这里注意必须指定sheetNo + WriteSheet writeSheet = EasyExcel.writerSheet(i, sheetName + "(" + i + ")").build(); + //这里是将查询的数据分为若干个sheet页 + subList = listdata.subList(i * MAX_ROWS_ONE_SHEET, i == sheetNum - 1 ? listdata.size() : (i + 1) * MAX_ROWS_ONE_SHEET); + excelWriter.write(subList, writeSheet); + } + } + } diff --git a/secret-boot-framework-jpa/src/main/java/cn/chenc/framework/jpa/model/BaseEntity.java b/secret-boot-framework-jpa/src/main/java/cn/chenc/framework/jpa/model/BaseEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..23db7f6aaf6c8d64a835fac63fa3f15491326623 --- /dev/null +++ b/secret-boot-framework-jpa/src/main/java/cn/chenc/framework/jpa/model/BaseEntity.java @@ -0,0 +1,61 @@ +package cn.chenc.framework.jpa.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.Map; + +/** + *  @description: 实体类基类 + *  @author secret + *  @date 2021/5/13 17:54 + * + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class BaseEntity { + + public final static int DEFAULT_PAGE_SIZE = 10; + + //每页数 + private int pageSize = 0; + + //分页当前索引 + private int pageIndex = 0; + + //排序字段 + private String orderField; + + //排序方向 + private String orderDirection; + + //关键字 + private String keywords; + + //开始时间 + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date startDate; + + //结束时间 + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date endDate; + + //数据校验是否通过,0通过,1未通过,默认空则为通过 + private Integer isValidator; + + /** 请求参数扩展 */ + private Map params; + + + public int getPageSize() { + return pageSize > 0 ? pageSize : DEFAULT_PAGE_SIZE; + } + + public int getPageStart() { + return pageIndex > 0 ? (pageIndex - 1) * getPageSize() : 0; + } + + +} diff --git a/secret-boot-framework-mybatisplus/src/main/java/cn/chenc/framework/mybatisplus/model/BaseConditionVO.java b/secret-boot-framework-mybatisplus/src/main/java/cn/chenc/framework/mybatisplus/model/BaseEntity.java similarity index 95% rename from secret-boot-framework-mybatisplus/src/main/java/cn/chenc/framework/mybatisplus/model/BaseConditionVO.java rename to secret-boot-framework-mybatisplus/src/main/java/cn/chenc/framework/mybatisplus/model/BaseEntity.java index d59e8a6ea21fbfcb261ccbbca094bf5fd318fe62..841098ef6005f2c553fe936b4ba63ea9d44e203f 100644 --- a/secret-boot-framework-mybatisplus/src/main/java/cn/chenc/framework/mybatisplus/model/BaseConditionVO.java +++ b/secret-boot-framework-mybatisplus/src/main/java/cn/chenc/framework/mybatisplus/model/BaseEntity.java @@ -11,12 +11,10 @@ import java.util.Map; /** * @author secret * 实体类基类 - * @version 1.0 - * @date 2018/4/16 16:26 */ @Data @EqualsAndHashCode(callSuper = false) -public class BaseConditionVO { +public class BaseEntity { public final static int DEFAULT_PAGE_SIZE = 10; diff --git a/secret-boot-framework-mybatisplus/src/main/java/cn/chenc/framework/mybatisplus/util/Query.java b/secret-boot-framework-mybatisplus/src/main/java/cn/chenc/framework/mybatisplus/util/Query.java index 70fa79c9c6948a976ae27e591f1b5d92a47f6d9f..028c5377538e6e1ed7246ec42d933e4464bd6586 100644 --- a/secret-boot-framework-mybatisplus/src/main/java/cn/chenc/framework/mybatisplus/util/Query.java +++ b/secret-boot-framework-mybatisplus/src/main/java/cn/chenc/framework/mybatisplus/util/Query.java @@ -1,6 +1,6 @@ package cn.chenc.framework.mybatisplus.util; -import cn.chenc.framework.mybatisplus.model.BaseConditionVO; +import cn.chenc.framework.mybatisplus.model.BaseEntity; import cn.chenc.framework.mybatisplus.xss.SqlFilter; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.OrderItem; @@ -23,7 +23,7 @@ public class Query { * @param params 参数 * @return 分页对象 */ - public IPage getPage(BaseConditionVO params) { + public IPage getPage(BaseEntity params) { return this.getPage(params, null, null); } @@ -34,7 +34,7 @@ public class Query { * @param isAsc 是否升序(指定排序字段有效) * @return 分页对象 */ - public IPage getPage(BaseConditionVO params, String defaultOrderField, Boolean isAsc) { + public IPage getPage(BaseEntity params, String defaultOrderField, Boolean isAsc) { // 分页参数 int pageIndex = 1; int pageSize = 10; diff --git a/secret-boot-framework-security/src/main/java/cn/chenc/framework/security/model/LoginUser.java b/secret-boot-framework-security/src/main/java/cn/chenc/framework/security/model/LoginUser.java index 39cbc537aa51de6a9921b712e16a7c6ca0ba6e6a..02284010ef487b8aee52f98f49dff8588ddbdbdc 100644 --- a/secret-boot-framework-security/src/main/java/cn/chenc/framework/security/model/LoginUser.java +++ b/secret-boot-framework-security/src/main/java/cn/chenc/framework/security/model/LoginUser.java @@ -54,6 +54,11 @@ public class LoginUser implements UserDetails, Serializable { */ private String os; + /** + * 角色列表 + */ + private Set roles; + /** * 权限列表 */ @@ -207,6 +212,14 @@ public class LoginUser implements UserDetails, Serializable { this.expireTime = expireTime; } + public Set getRoles() { + return roles; + } + + public void setRoles(Set roles) { + this.roles = roles; + } + public Set getPermissions() { return permissions; diff --git a/secret-boot-framework-security/src/main/java/cn/chenc/framework/security/service/PermissionService.java b/secret-boot-framework-security/src/main/java/cn/chenc/framework/security/service/PermissionService.java new file mode 100644 index 0000000000000000000000000000000000000000..38abb1ed87be24d6eebe3f9aa6c246129b9c4094 --- /dev/null +++ b/secret-boot-framework-security/src/main/java/cn/chenc/framework/security/service/PermissionService.java @@ -0,0 +1,148 @@ +package cn.chenc.framework.security.service; + + +import cn.chenc.framework.core.model.request.RequestHolder; +import cn.chenc.framework.core.util.StringUtils; +import cn.chenc.framework.security.jwt.SecurityJwtTemplate; +import cn.chenc.framework.security.model.LoginUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.Set; + +/** + * 自定义权限实现 + * + */ +@Service("ss") +public class PermissionService +{ + /** 所有权限标识 */ + private static final String ALL_PERMISSION = "*:*:*"; + + /** 管理员角色权限标识 */ + private static final String SUPER_ADMIN = "admin"; + + private static final String ROLE_DELIMETER = ","; + + private static final String PERMISSION_DELIMETER = ","; + + @Autowired(required = false) + private SecurityJwtTemplate securityJwtTemplate; + + /** + * 验证用户是否具备某权限 + * + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + public boolean hasPermi(String permission) { + if (StringUtils.isEmpty(permission)) { + return false; + } + LoginUser loginUser = securityJwtTemplate.getLoginUser(RequestHolder.getRequest()); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) { + return false; + } + return hasPermissions(loginUser.getPermissions(), permission); + } + + /** + * 验证用户是否不具备某权限,与 hasPermi逻辑相反 + * + * @param permission 权限字符串 + * @return 用户是否不具备某权限 + */ + public boolean lacksPermi(String permission) { + return hasPermi(permission) != true; + } + + /** + * 验证用户是否具有以下任意一个权限 + * + * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表 + * @return 用户是否具有以下任意一个权限 + */ + public boolean hasAnyPermi(String permissions) { + if (StringUtils.isEmpty(permissions)) { + return false; + } + LoginUser loginUser = securityJwtTemplate.getLoginUser(RequestHolder.getRequest()); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) { + return false; + } + Set authorities = loginUser.getPermissions(); + for (String permission : permissions.split(PERMISSION_DELIMETER)) { + if (permission != null && hasPermissions(authorities, permission)) { + return true; + } + } + return false; + } + + /** + * 判断用户是否拥有某个角色 + * + * @param role 角色字符串 + * @return 用户是否具备某角色 + */ + public boolean hasRole(String role) { + if (StringUtils.isEmpty(role)) { + return false; + } + LoginUser loginUser = securityJwtTemplate.getLoginUser(RequestHolder.getRequest()); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getRoles())) { + return false; + } + for (String roleKey : loginUser.getRoles()) { + if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) { + return true; + } + } + return false; + } + + /** + * 验证用户是否不具备某角色,与 isRole逻辑相反。 + * + * @param role 角色名称 + * @return 用户是否不具备某角色 + */ + public boolean lacksRole(String role) { + return hasRole(role) != true; + } + + /** + * 验证用户是否具有以下任意一个角色 + * + * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表 + * @return 用户是否具有以下任意一个角色 + */ + public boolean hasAnyRoles(String roles) { + if (StringUtils.isEmpty(roles)) { + return false; + } + LoginUser loginUser = securityJwtTemplate.getLoginUser(RequestHolder.getRequest()); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getRoles())) { + return false; + } + for (String role : roles.split(ROLE_DELIMETER)) { + if (hasRole(role)) { + return true; + } + } + return false; + } + + /** + * 判断是否包含权限 + * + * @param permissions 权限列表 + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + private boolean hasPermissions(Set permissions, String permission) { + return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission)); + } +} diff --git a/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/model/JwtToken.java b/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/model/JwtToken.java index 43a70a1a1c50b8e7da41e2c6c6e60e9e22371368..36eb3e3b403269bcf16f135b629180017e21171e 100644 --- a/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/model/JwtToken.java +++ b/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/model/JwtToken.java @@ -3,7 +3,7 @@ package cn.chenc.framework.shiro.model; import org.apache.shiro.authc.AuthenticationToken; /** - *  @description: TODO + *  @description: 自定义实现AuthenticationToken *  @author secret *  @date 2021/5/4 1:33 * diff --git a/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/model/LoginUser.java b/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/model/LoginUser.java index 077a4117303bcc79c4129014bc9b4fb84e862edd..f0d3763f719674eeaff8f85caf0dcc70fc5d4825 100644 --- a/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/model/LoginUser.java +++ b/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/model/LoginUser.java @@ -50,6 +50,11 @@ public class LoginUser implements Serializable { */ private String os; + /** + * 角色列表 + */ + private Set roles; + /** * 权限列表 */ @@ -158,6 +163,14 @@ public class LoginUser implements Serializable { this.os = os; } + public Set getRoles() { + return roles; + } + + public void setRoles(Set roles) { + this.roles = roles; + } + public Set getPermissions() { return permissions; } diff --git a/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/util/ShiroUtils.java b/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/util/ShiroUtils.java index 59688b56a52bd87af9a646c4d738d24ba0338256..1bee357b8e2b2c1970bda6479160d3326f4b03ba 100644 --- a/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/util/ShiroUtils.java +++ b/secret-boot-framework-shiro/src/main/java/cn/chenc/framework/shiro/util/ShiroUtils.java @@ -10,7 +10,7 @@ import org.apache.shiro.subject.Subject; /** * shiro 工具类 * - * @author ruoyi + * @author secret */ public class ShiroUtils { public static Subject getSubject() {