From 1a96ce465442e58ff76a3ef4896a3d1b45ef43e2 Mon Sep 17 00:00:00 2001 From: zhenggm Date: Thu, 8 Sep 2022 16:38:06 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B3=BB=E7=BB=9F=EF=BC=9A=E6=8B=A6=E6=88=AA?= =?UTF-8?q?=E5=99=A8=E8=B0=83=E6=95=B4=EF=BC=8C=E7=BB=9F=E4=B8=80=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=A4=84=E7=90=86=EF=BC=8C=E9=98=B2=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E6=8C=87=E7=BA=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spring/controller/FileDownloadController.java | 5 - .../spring/controller/FileUploadController.java | 10 -- .../smtweb/system/bpm/web/login/AuthService.java | 5 - .../cc/smtweb/framework/core/CoreInterceptor.java | 9 + .../smtweb/framework/core/annotation/SwPerm.java | 26 --- .../framework/core/cache/SessionCacheFactory.java | 9 +- .../cc/smtweb/framework/core/common/SwConsts.java | 9 + .../framework/core/exception/BizException.java | 15 ++ .../core/exception/SwExceptionHandler.java | 29 +++ .../framework/core/mvc/config/WebMvcConfig.java | 2 +- .../core/mvc/controller/MethodAccessManager.java | 8 +- .../core/mvc/controller/SwResponseBodyAdvice.java | 34 ++++ .../core/mvc/controller/access/IMethodAccess.java | 6 - .../core/mvc/controller/access/MethodAccess.java | 6 +- .../core/mvc/controller/scan/MethodParser.java | 20 +-- .../realm/interceptor/AbstractPermInterceptor.java | 110 ------------ .../interceptor/AuthorizationInterceptor.java | 42 ----- .../mvc/realm/interceptor/PermInterceptor.java | 27 --- .../smtweb/framework/core/session/SessionUtil.java | 197 +++++++++++++++++++-- smtweb-framework/pom.xml | 5 + 20 files changed, 291 insertions(+), 283 deletions(-) delete mode 100644 smtweb-framework/core/src/main/java/cc/smtweb/framework/core/annotation/SwPerm.java create mode 100644 smtweb-framework/core/src/main/java/cc/smtweb/framework/core/exception/SwExceptionHandler.java create mode 100644 smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/SwResponseBodyAdvice.java delete mode 100644 smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/AbstractPermInterceptor.java delete mode 100644 smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/AuthorizationInterceptor.java delete mode 100644 smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/PermInterceptor.java diff --git a/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileDownloadController.java b/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileDownloadController.java index b21cc62..6e3df50 100644 --- a/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileDownloadController.java +++ b/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileDownloadController.java @@ -32,9 +32,6 @@ public class FileDownloadController { @Autowired private FilePathGenerator filePathGenerator; - @Autowired - private RedisManager redisManager; - /** * path方式下载文件 */ @@ -56,8 +53,6 @@ public class FileDownloadController { @RequestParam(value = "noCache", required = false) Boolean noCache, HttpServletRequest request ) throws FileNotFoundException { - SessionUtil.checkSession(request, redisManager); - File file = new File(filePathGenerator.getFileDiskPath(path)); if (!file.exists()) { diff --git a/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileUploadController.java b/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileUploadController.java index 260826f..bce6c81 100644 --- a/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileUploadController.java +++ b/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileUploadController.java @@ -30,9 +30,6 @@ public class FileUploadController { private DbEngine dbEngine; @Autowired - private RedisManager redisManager; - - @Autowired private ImageAttachDao imageAttachDao; // TODO: 权限处理,临时文件处理 @@ -44,7 +41,6 @@ public class FileUploadController { @RequestParam(value = "keepName", required = false) Boolean keepName, HttpServletRequest request ) { - SessionUtil.checkSession(request, redisManager); return uploadFile(path, file, ThumbImage.type(thumb), thumbHeight, insert, keepName); } @@ -54,8 +50,6 @@ public class FileUploadController { @RequestParam(value = "thumbHeight", required = false) Integer thumbHeight, @RequestParam(value = "commit", required = false) Boolean insert, HttpServletRequest request) { - SessionUtil.checkSession(request, redisManager); - MultipartFile file = MemMultipartFile.build(data.getData()); if (file == null) { return R.error("数据内容格式有错"); @@ -70,7 +64,6 @@ public class FileUploadController { @RequestParam(value = "commit", required = false) Boolean insert, @RequestParam(value = "keepName", required = false) Boolean keepName, HttpServletRequest request) { - SessionUtil.checkSession(request, redisManager); return uploadFile(path, file, ThumbImage.TYPE_AVATAR, size, insert, keepName); } @@ -81,7 +74,6 @@ public class FileUploadController { @RequestParam(value = "thumbHeight", required = false) Integer thumbHeight, @RequestParam(value = "keepName", required = false) Boolean keepName, HttpServletRequest request) { - SessionUtil.checkSession(request, redisManager); return uploadFile(path, file, ThumbImage.type(thumb), thumbHeight, true, keepName); } @@ -143,8 +135,6 @@ public class FileUploadController { // TODO: 修改为安全的后台删除方式 @PostMapping("/fs/remove") public R remove(@RequestParam(value = "filePath") String filePath, HttpServletRequest request) { - SessionUtil.checkSession(request, redisManager); - File file = new File(filePathGenerator.getFileDiskPath(filePath)); if (file.exists() && file.isFile()) { if (file.delete()) { diff --git a/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/login/AuthService.java b/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/login/AuthService.java index 9e961c3..2ee2eb7 100644 --- a/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/login/AuthService.java +++ b/smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/login/AuthService.java @@ -2,7 +2,6 @@ package cc.smtweb.system.bpm.web.login; import cc.smtweb.framework.core.annotation.SwBody; import cc.smtweb.framework.core.annotation.SwParam; -import cc.smtweb.framework.core.annotation.SwPerm; import cc.smtweb.framework.core.annotation.SwService; import cc.smtweb.framework.core.common.R; import cc.smtweb.framework.core.common.SwMap; @@ -28,7 +27,6 @@ public class AuthService { @SwParam private SessionManager sessionManager; - @SwPerm() public R getParty(@SwParam("username") String username) { Set partySet = PartyCache.getInstance().getTopSet(); List list = new ArrayList<>(); @@ -43,7 +41,6 @@ public class AuthService { return R.success(list); } - @SwPerm(SwPerm.NONE) public R login(@SwBody LoginVO loginPO) { SwMap data = new SwMap(); User user = null; @@ -96,12 +93,10 @@ public class AuthService { return R.success(data); } - @SwPerm() public R ping(@SwParam("msg") String msg) { return R.success(msg); } - @SwPerm("user:edit") public R config(@SwParam("username") String username) { return R.success("config: " + username); } diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/CoreInterceptor.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/CoreInterceptor.java index d05da64..fae124f 100644 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/CoreInterceptor.java +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/CoreInterceptor.java @@ -1,7 +1,15 @@ package cc.smtweb.framework.core; +import cc.smtweb.framework.core.cache.redis.RedisManager; import cc.smtweb.framework.core.common.SwConsts; import cc.smtweb.framework.core.exception.BizException; +import cc.smtweb.framework.core.mvc.controller.IEditor; +import cc.smtweb.framework.core.mvc.realm.exception.ForbiddenException; +import cc.smtweb.framework.core.mvc.realm.exception.UnauthenticatedException; +import cc.smtweb.framework.core.session.SessionUtil; +import cc.smtweb.framework.core.session.UserSession; +import cc.smtweb.framework.core.util.NumberUtil; +import org.apache.commons.lang3.StringUtils; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; @@ -15,6 +23,7 @@ public class CoreInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!SwConsts.SysParam.SYS_STARTED) throw new BizException("系统启动中,请稍候..."); + SessionUtil.checkSession(request); return HandlerInterceptor.super.preHandle(request, response, handler); } diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/annotation/SwPerm.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/annotation/SwPerm.java deleted file mode 100644 index 2487667..0000000 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/annotation/SwPerm.java +++ /dev/null @@ -1,26 +0,0 @@ -package cc.smtweb.framework.core.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 被该注释修饰的方法都会经过切面拦截校验权限,默认是需要已登录权限 - * - * @author kevin - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -public @interface SwPerm { - /** - * 无权限控制的值,在函数上注解@SwPerm(SwPerm.NONE) - */ - static final String NONE = "*"; - static final String SESSION = ""; - - /** - * 权限定义值 - */ - String value() default SESSION; -} diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/cache/SessionCacheFactory.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/cache/SessionCacheFactory.java index 8ad6fdc..ca1e4b5 100644 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/cache/SessionCacheFactory.java +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/cache/SessionCacheFactory.java @@ -8,7 +8,7 @@ import java.util.concurrent.ConcurrentHashMap; */ public class SessionCacheFactory { private static SessionCacheFactory INSTANCE = null; - private Map buffer = new ConcurrentHashMap<>(); + private Map buffer = new ConcurrentHashMap<>(); private SessionCacheFactory() { } @@ -27,10 +27,10 @@ public class SessionCacheFactory { //得到用户缓存对象 public SessionCache getUserCache(long userId) { - return getUserCache(userId, 0L); + return getCache(String.valueOf(userId), 0L); } - public SessionCache getUserCache(long userId, long timeout) { + public SessionCache getCache(String userId, long timeout) { SessionCache cache; cache = buffer.get(userId); @@ -41,11 +41,12 @@ public class SessionCacheFactory { buffer.put(userId, cache); } return cache; - } //删除用户缓存 public void remove(String userId) { buffer.remove(userId); } + + } diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/common/SwConsts.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/common/SwConsts.java index d76fb3d..a4149f5 100644 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/common/SwConsts.java +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/common/SwConsts.java @@ -13,8 +13,17 @@ public interface SwConsts { public static String RUN_PROJECTS = ""; } + //错误码 + interface ErrorCode { + //未登录 + int NO_LOGIN = 101; + //指纹错误 + int TOKEN_INVALID = 102; + } + //启动顺序默认值 int DEFAULT_ORDER = 1; + //缓存中:树节点按parent的key String KEY_PARENT_ID = "pr"; //级次码、字符串连接符 diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/exception/BizException.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/exception/BizException.java index fe097be..8db6559 100644 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/exception/BizException.java +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/exception/BizException.java @@ -10,6 +10,8 @@ public class BizException extends RuntimeException { * */ private static final long serialVersionUID = 1L; + //错误编号 + private int code = 0; public BizException() { super(); @@ -23,7 +25,20 @@ public class BizException extends RuntimeException { super(message); } + public BizException(int code) { + super(); + this.code = code; + } + public BizException(int code, String message) { + super(message); + this.code = code; + } + public BizException(Throwable cause) { super(cause.getMessage(), cause); } + + public int getCode() { + return code; + } } diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/exception/SwExceptionHandler.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/exception/SwExceptionHandler.java new file mode 100644 index 0000000..e7b24df --- /dev/null +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/exception/SwExceptionHandler.java @@ -0,0 +1,29 @@ +package cc.smtweb.framework.core.exception; + +import cc.smtweb.framework.core.common.R; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * Created by Akmm at 2022-09-07 20:13 + * 异常统一处理 + */ +@ControllerAdvice +public class SwExceptionHandler { + /** + * 系统异常处理 + * + * @param e + * @return + */ + @ExceptionHandler(Exception.class) + @ResponseBody + public R error(Exception e) { + if (e instanceof BizException) { + return R.error(((BizException) e).getCode(), e.getMessage()); + } + e.printStackTrace(); + return R.error("系统异常,请联系技术支持人员!"); + } +} diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/config/WebMvcConfig.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/config/WebMvcConfig.java index 83c4bb1..dafb036 100644 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/config/WebMvcConfig.java +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/config/WebMvcConfig.java @@ -64,7 +64,7 @@ public class WebMvcConfig implements WebMvcConfigurer { @Bean public MethodAccessManager methodAccessManager(CacheManager cacheManager) { - return new MethodAccessManager(redisManager, cacheManager); + return new MethodAccessManager(cacheManager); } @Override diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/MethodAccessManager.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/MethodAccessManager.java index 9c76896..4041fe0 100644 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/MethodAccessManager.java +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/MethodAccessManager.java @@ -8,7 +8,6 @@ import cc.smtweb.framework.core.mvc.SchedulerManager; import cc.smtweb.framework.core.mvc.controller.access.IMethodAccess; import cc.smtweb.framework.core.mvc.controller.access.MethodAccess; import cc.smtweb.framework.core.mvc.controller.scan.BeanManager; -import cc.smtweb.framework.core.mvc.realm.interceptor.PermInterceptor; import cc.smtweb.framework.core.mvc.realm.service.PermChecker; import cc.smtweb.framework.core.mvc.scheduler.SchedulerTaskManager; import lombok.Getter; @@ -27,15 +26,13 @@ import java.util.Map; public class MethodAccessManager { private Map controllers; private IBeanContext beanContext; - private PermInterceptor permInterceptor; private SchedulerTaskManager schedulerTaskManager; private MethodAccess[] destroyMethods; @Getter private CacheManager cacheManager; - public MethodAccessManager(RedisManager redisManager, CacheManager cacheManager) { - permInterceptor = new PermInterceptor(redisManager); + public MethodAccessManager(CacheManager cacheManager) { this.cacheManager = cacheManager; } @@ -47,8 +44,6 @@ public class MethodAccessManager { IMethodAccess methodAccess = controllers.get(url); if (methodAccess != null) { - permInterceptor.preHandle(request, methodAccess.getPerm()); - return methodAccess.invoke(beanContext, params, body, request); } @@ -71,7 +66,6 @@ public class MethodAccessManager { this.beanContext = beanManager.getBeanContext(); this.controllers = beanManager.getControllers(); this.destroyMethods = beanManager.loadDestroyMethods(); - this.permInterceptor.setCache(cache); // 启动定时任务 this.schedulerTaskManager = SchedulerTaskManager.build(beanContext, beanManager.getTasks()); diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/SwResponseBodyAdvice.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/SwResponseBodyAdvice.java new file mode 100644 index 0000000..1934c8c --- /dev/null +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/SwResponseBodyAdvice.java @@ -0,0 +1,34 @@ +package cc.smtweb.framework.core.mvc.controller; + +import cc.smtweb.framework.core.common.R; +import cc.smtweb.framework.core.session.SessionUtil; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +/** + * Created by Akmm at 2022-09-08 16:03 + * 统一添加指纹 + */ +@ControllerAdvice +public class SwResponseBodyAdvice implements ResponseBodyAdvice { + @Override + public boolean supports(MethodParameter returnType, Class converterType) { + Class targetClass = returnType.getMethod().getDeclaringClass(); + + return true; + } + + @Override + public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { + if (body instanceof R) { + SessionUtil.setFingerValue(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(), (R)body); + } + return body; + } +} diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/access/IMethodAccess.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/access/IMethodAccess.java index ddfef8c..4f67e94 100644 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/access/IMethodAccess.java +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/access/IMethodAccess.java @@ -46,10 +46,4 @@ public interface IMethodAccess { */ String fullName(); - /** - * API权限 - * - * @return 权限串 - */ - String getPerm(); } diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/access/MethodAccess.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/access/MethodAccess.java index e322bcd..9bb7395 100644 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/access/MethodAccess.java +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/access/MethodAccess.java @@ -22,14 +22,12 @@ import java.util.Map; public class MethodAccess implements IMethodAccess { private final ControllerAccess controllerAccess; private final Method method; - @Getter - private final String perm; + private final MethodParamAccess[] paramBinds; - public MethodAccess(ControllerAccess controllerAccess, Method method, String perm, MethodParamAccess[] paramBinds) { + public MethodAccess(ControllerAccess controllerAccess, Method method, MethodParamAccess[] paramBinds) { this.controllerAccess = controllerAccess; this.method = method; - this.perm = perm; this.paramBinds = paramBinds; } diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/scan/MethodParser.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/scan/MethodParser.java index 34229ea..3e0b4a9 100644 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/scan/MethodParser.java +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/scan/MethodParser.java @@ -35,20 +35,13 @@ public class MethodParser { public void parse(Class clazz, ControllerAccess controllerAccess, boolean isApi) throws ParseException { // this.controllerAccess = controllerAccess; - // 服务的默认权限 - String classPerm = ""; - SwPerm swPerm = clazz.getAnnotation(SwPerm.class); - if (swPerm != null) { - classPerm = swPerm.value(); - } - // 扫描方法注解 for (Method m : clazz.getMethods()) { int modifier = m.getModifiers(); // && (R.class.isAssignableFrom(m.getReturnType())) if (Modifier.isPublic(modifier) && !Modifier.isStatic(modifier) && !Object.class.equals(m.getDeclaringClass())) { - MethodAccess methodAccess = parseMethod(controllerAccess, m, classPerm); + MethodAccess methodAccess = parseMethod(controllerAccess, m); if (scanContext.dealMethod(m, methodAccess)) { if (isApi) { @@ -81,7 +74,7 @@ public class MethodParser { } } - private MethodAccess parseMethod(ControllerAccess controllerAccess, Method method, String defaultPerm) { + private MethodAccess parseMethod(ControllerAccess controllerAccess, Method method) { Class[] paramTypes = method.getParameterTypes(); Annotation[][] paramAnnotations = method.getParameterAnnotations(); @@ -146,14 +139,7 @@ public class MethodParser { } } - // 得到权限注解 - String perm = defaultPerm; - SwPerm swPerm = method.getAnnotation(SwPerm.class); - if (swPerm != null) { - perm = swPerm.value(); - } - - return new MethodAccess(controllerAccess, method, perm, paramBinds); + return new MethodAccess(controllerAccess, method, paramBinds); } } diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/AbstractPermInterceptor.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/AbstractPermInterceptor.java deleted file mode 100644 index 558047c..0000000 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/AbstractPermInterceptor.java +++ /dev/null @@ -1,110 +0,0 @@ -package cc.smtweb.framework.core.mvc.realm.interceptor; - -import cc.smtweb.framework.core.annotation.SwPerm; -import cc.smtweb.framework.core.cache.ISwCache; -import cc.smtweb.framework.core.cache.redis.RedisManager; -import cc.smtweb.framework.core.mvc.controller.IEditor; -import cc.smtweb.framework.core.mvc.realm.exception.ForbiddenException; -import cc.smtweb.framework.core.mvc.realm.exception.UnauthenticatedException; -import cc.smtweb.framework.core.mvc.realm.service.PermCheckItem; -import cc.smtweb.framework.core.mvc.realm.service.PermChecker; -import cc.smtweb.framework.core.session.SessionUtil; -import cc.smtweb.framework.core.session.UserSession; -import org.apache.commons.lang3.StringUtils; - -import javax.servlet.http.HttpServletRequest; - -public class AbstractPermInterceptor { - private final RedisManager redisManager; - private ISwCache cacheService; - - public AbstractPermInterceptor(RedisManager redisManager) { - this.redisManager = redisManager; - } - - public void setCache(ISwCache cacheService) { - this.cacheService = cacheService; - } - - protected boolean handle(HttpServletRequest request, String permissionValue) { - // 如果注解为null, 说明不需要拦截, 直接放过 - if (SwPerm.NONE.equals(permissionValue)) { - return true; - } - - // redis读取session,判断是否登录 - String token = SessionUtil.readToken(request); - if ("design".equals(token)) return true; - if (StringUtils.isBlank(token)) { - throw new UnauthenticatedException("not find Auth-Token in header"); - } - - UserSession us = redisManager.get(token, UserSession.class); - if (us == null) { - throw new UnauthenticatedException("not find UserSession by token: " + token); - } - - request.setAttribute(IEditor.USER_TOKEN, token); - request.setAttribute(IEditor.USER_SESSION, us); - - // 如果标记了权限注解,则判断权限 - if (checkPermission(permissionValue, us)) { - // 更新Token redis TTL - redisManager.expire(token, RedisManager.SESSION_EXPIRE_SEC); - return true; - } else { - throw new ForbiddenException("user not permission: " + permissionValue); - } - } - - /** - * 权限检查 - */ - private boolean checkPermission(String permissionValue, UserSession us) { - if (StringUtils.isBlank(permissionValue)) { - return true; - } - - // 从本地缓存或数据库中获取该用户的权限信息 - PermChecker permissionSet = cacheService.get(us.getUserId()); - -// if (MapUtils.isEmpty(permissionSet)) { -// throw new ForbiddenException("empty permission"); -// } - - PermCheckItem permChecker = permissionSet.get(permissionValue); - - if (permChecker != null) { - return true; - } - - while (true) { - permissionValue = getParentPermValue(permissionValue); - - if (permissionValue != null) { - permChecker = permissionSet.get(permissionValue); - if (permChecker != null && permChecker.isPerfixMath()) { - return true; - } - } else { - break; - } - } - - return false; - } - - private static String getParentPermValue(String permissionValue) { - if (permissionValue.length() > 0) { - - int pos = permissionValue.lastIndexOf(':'); - if (pos > 0) { - return permissionValue.substring(0, pos); - } - - return ""; - } - - return null; - } -} diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/AuthorizationInterceptor.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/AuthorizationInterceptor.java deleted file mode 100644 index b6430f0..0000000 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/AuthorizationInterceptor.java +++ /dev/null @@ -1,42 +0,0 @@ -package cc.smtweb.framework.core.mvc.realm.interceptor; - -import cc.smtweb.framework.core.annotation.SwPerm; -import cc.smtweb.framework.core.cache.redis.RedisManager; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerInterceptor; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * 暂时未使用,spring的拦截器方式判断权限 - */ -public class AuthorizationInterceptor extends AbstractPermInterceptor implements HandlerInterceptor { - - public AuthorizationInterceptor(RedisManager redisManager) { - super(redisManager); - } - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { - if (handler instanceof HandlerMethod) { - HandlerMethod handlerMethod = (HandlerMethod) handler; - // 获取方法上的注解 - SwPerm requiredSwPerm = handlerMethod.getMethod().getAnnotation(SwPerm.class); - // 如果方法上的注解为空 则获取类的注解 - if (requiredSwPerm == null) { - requiredSwPerm = handlerMethod.getMethod().getDeclaringClass().getAnnotation(SwPerm.class); - } - - String requiredValue = null; - if (requiredSwPerm != null) { - requiredValue = requiredSwPerm.value(); - } - - return super.handle(request, requiredValue); - } - - return true; - } -} diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/PermInterceptor.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/PermInterceptor.java deleted file mode 100644 index 0edd4b0..0000000 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/realm/interceptor/PermInterceptor.java +++ /dev/null @@ -1,27 +0,0 @@ -package cc.smtweb.framework.core.mvc.realm.interceptor; - -import cc.smtweb.framework.core.cache.redis.RedisManager; - -import javax.servlet.http.HttpServletRequest; - -/** - * 权限拦截器,在API请求处理中一起完成 - * - * @author xkliu - */ -public class PermInterceptor extends AbstractPermInterceptor { - public PermInterceptor(RedisManager redisManager) { - super(redisManager); - } - - /** - * 校验用户是否有API权限 - * - * @param request http请求 - * @param permissionValue 权限值 - * @return 是否有权限 - */ - public boolean preHandle(HttpServletRequest request, String permissionValue) { - return super.handle(request, permissionValue); - } -} diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/session/SessionUtil.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/session/SessionUtil.java index 2237a24..32c51c0 100644 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/session/SessionUtil.java +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/session/SessionUtil.java @@ -1,12 +1,22 @@ package cc.smtweb.framework.core.session; +import cc.smtweb.framework.core.cache.SessionCache; +import cc.smtweb.framework.core.cache.SessionCacheFactory; import cc.smtweb.framework.core.cache.redis.RedisManager; +import cc.smtweb.framework.core.common.R; +import cc.smtweb.framework.core.common.SwConsts; +import cc.smtweb.framework.core.exception.BizException; import cc.smtweb.framework.core.mvc.controller.IEditor; import cc.smtweb.framework.core.mvc.realm.exception.UnauthenticatedException; +import cc.smtweb.framework.core.util.NumberUtil; +import cc.smtweb.framework.core.util.StringUtil; import org.apache.commons.lang3.StringUtils; import org.springframework.web.context.request.RequestContextHolder; import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; /** * 〈session工具类〉 @@ -15,6 +25,94 @@ import javax.servlet.http.HttpServletRequest; * @since 1.0.0 */ public class SessionUtil { + //登录令牌header名 + private final static String KEY_HEADER_SESSION = "Auth-Token"; + //url参数名 + private final static String KEY_PARAM_SESSION = "auth_token"; + + //防止重复提交指纹-header名 + private final static String KEY_HEADER_FP_KEY = "Fpk_Token"; + private final static String KEY_HEADER_FP_VAL = "Fpv_Token"; + //url参数名 + private final static String KEY_PARAM_FP_KEY = "fpk"; + private final static String KEY_PARAM_FP_VAL = "fpv"; + + //不需要校验登录的url + public static List notLoginUrl = new ArrayList<>(); + /*//不需要切换数据源的url,强制用主库 + public static List notSetDbUrl = new ArrayList<>();*/ + //不需要验证合法性的url + public static List notCheckUrlValid = new ArrayList<>(); + //不算用户交互操作的url,用于管理session失效 + public static List notInterActiveUrl = new ArrayList<>(); + static { + notLoginUrl.add("/db/*.do"); + notLoginUrl.add("/custdb/*.do"); + notLoginUrl.add("/attach/upload.do"); + notLoginUrl.add("/attach/download.do"); + notLoginUrl.add("/attach/uploadBase64.do"); + + notCheckUrlValid.add("/db/*.do"); + notCheckUrlValid.add("/custdb/*.do"); + notCheckUrlValid.add("/cust/common/httpService/service.do"); + notCheckUrlValid.add("/attach/upload.do"); + notCheckUrlValid.add("/attach/uploadBase64.do"); + + } + + private static void addUrl(String url, List list) { + list.add(url); + } + + //是否不需要url校验 + private static boolean isMatchUrl(String lasturi, List list) { + if (list.contains(lasturi)) return true; + for (String s: list){ + if (StringUtil.match(s, lasturi)) return true; + } + return false; + } + + //是否不需要登录验证 + public static boolean isNoLogin(String lasturi) { + return isMatchUrl(lasturi, notLoginUrl); + } + + //增加不需要登录的Uri + public static void addNoLoginUri(String uri) { + addUrl(uri, notLoginUrl); + } + + /*//是否不需要切换库 + public static boolean isNoSetDb(String lasturi) { + return isMatchUrl(lasturi, notSetDbUrl); + } + + //增加不需要登录的Uri + public static void addNoSetDbUrl(String uri) { + addUrl(uri, notSetDbUrl); + }*/ + + //是否不需要url校验 + public static boolean isNoCheckValid(String lasturi) { + return isMatchUrl(lasturi, notCheckUrlValid); + } + + //增加不需要校验合法性的Uri + public static void addNoCheckValidUri(String uri) { + addUrl(uri, notCheckUrlValid); + } + + //不算用户交互操作 + public static boolean isNoInterActive(String lasturi) { + return isMatchUrl(lasturi, notInterActiveUrl); + } + + //不算用户交互操作 + public static void addNoInterActiveUri(String uri) { + addUrl(uri, notInterActiveUrl); + } + private SessionUtil() { } @@ -23,41 +121,102 @@ public class SessionUtil { } public static String readToken(HttpServletRequest request) { - String token = request.getHeader("Auth-Token"); + return readToken(request, KEY_HEADER_SESSION, KEY_PARAM_SESSION); + } + + public static String readFingerKey(HttpServletRequest request) { + return readToken(request, KEY_HEADER_FP_KEY, KEY_PARAM_FP_KEY); + } + + public static int readFingerVal(HttpServletRequest request) { + return NumberUtil.getIntIgnoreErr(readToken(request, KEY_HEADER_FP_VAL, KEY_PARAM_FP_VAL)); + } + + private static String readToken(HttpServletRequest request, String headerName, String paramName) { + String token = request.getHeader(headerName); if (token == null) { - token = request.getParameter("auth_token"); + token = request.getParameter(paramName); } return token; } - public static UserSession checkSession(HttpServletRequest request, RedisManager redisManager) { - String token = readToken(request); + //无效登录异常 + public static void throwNoLogin() { + throw new BizException(SwConsts.ErrorCode.NO_LOGIN); + } - if (StringUtils.isBlank(token)) { - throw new UnauthenticatedException("not find Auth-Token in header"); - } + //校验是否登录 + private static void checkLogin(HttpServletRequest request) { - UserSession us = redisManager.get(token, UserSession.class); - if (us == null) { - throw new UnauthenticatedException("not find UserSession by token: " + token); - } + } - return us; + private static AtomicInteger getFingerVal(String id, String tokenkey) {//取并+1 + SessionCache cache = SessionCacheFactory.getInstance().getCache(KEY_PARAM_FP_KEY, 1200L); + return cache.get(id + "_" + tokenkey); } + public static void checkSession(HttpServletRequest request) { + //校验登录 + String lasturi = getUriLast(request.getContextPath(), request.getServletPath()); + String token = readToken(request); + UserSession us = null; + if (StringUtils.isNotBlank(token)) { + us = RedisManager.getInstance().get(token, UserSession.class); + } + //校验登录 + final boolean isNologin ="design".equals(token) || isNoLogin(lasturi); + if (!isNologin) { + if (us == null) { + throwNoLogin(); + } - public static UserSession checkSession(String accessToken, RedisManager redisManager) { - if (StringUtils.isBlank(accessToken)) { - throw new UnauthenticatedException("not find Auth-Token in header"); + request.setAttribute(IEditor.USER_TOKEN, token); + request.setAttribute(IEditor.USER_SESSION, us); } - UserSession us = redisManager.get(accessToken, UserSession.class); - if (us == null) { - throw new UnauthenticatedException("not find UserSession by token: " + accessToken); + String fpk = readFingerKey(request); + if (!StringUtil.isEmpty(fpk)) { + //校验指纹 + String fpKey = us != null ? String.valueOf(us.getUserId()): request.getSession(true).getId(); + int fpv = readFingerVal(request); + + SessionCache cache = SessionCacheFactory.getInstance().getCache(KEY_PARAM_FP_KEY, 1200L); + AtomicInteger ai = cache.get(fpKey + "_" + fpk); + int bv = ai != null ? ai.get() : 0; + if (fpv != bv) { + throw new BizException(SwConsts.ErrorCode.TOKEN_INVALID, "指纹错误,请勿重复提交!"); + } } + } + + //设置指纹 + public static void setFingerValue(HttpServletRequest request, R r) { + String fpk = readFingerKey(request); + if (!StringUtil.isEmpty(fpk)) { + UserSession us = (UserSession) request.getAttribute(IEditor.USER_SESSION); + String fpKey = us != null ? String.valueOf(us.getUserId()): request.getSession(true).getId(); + SessionCache cache = SessionCacheFactory.getInstance().getCache(KEY_PARAM_FP_KEY, 1200L); + + AtomicInteger ai = cache.get(fpKey + "_" + fpk); + if (ai == null) { + cache.put(fpKey + "_" + fpk, new AtomicInteger(0)); + } + r.put(KEY_PARAM_FP_VAL, ai.getAndIncrement()); + } + } - return us; + /** + * 截取请求名称,如重 /${contextPath}/framework/loginpage.do中截出loginpage.do; + * + * @param contextPath /dfp + * @param uri /dfp/framework/loginpage.do + */ + private static String getUriLast(String contextPath, String uri) { + int index = uri.indexOf(contextPath+"/"); + if (index < 0) return uri; + if (index > 1) return uri; + return uri.substring(index + contextPath.length()); } // private static Session getShiroSession() { diff --git a/smtweb-framework/pom.xml b/smtweb-framework/pom.xml index 38a69dc..c08d83c 100644 --- a/smtweb-framework/pom.xml +++ b/smtweb-framework/pom.xml @@ -27,5 +27,10 @@ core bpm + + +