From 3a9fbb563e364aaab160983f52d5d947af2499fb Mon Sep 17 00:00:00 2001 From: valarchie <343928303@qq.com> Date: Sun, 30 Jul 2023 11:35:05 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=B0=86=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E9=87=8D=E5=A4=8D=E6=8F=90=E4=BA=A4=E5=92=8C=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E9=99=90=E6=B5=81=E9=87=8D=E6=9E=84=E5=8C=BA=E5=88=86=E4=B8=BA?= =?UTF-8?q?App=E5=92=8CWeb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/SysNoticeController.java | 3 +- .../infrastructure/annotations/RateLimit.java | 21 +++++- .../annotations/Unrepeatable.java | 68 +++++++++++++++++++ .../repeatsubmit/ResubmitInterceptor.java | 18 +---- .../security/AuthenticationUtils.java | 22 ++++++ 5 files changed, 111 insertions(+), 21 deletions(-) diff --git a/agileboot-admin/src/main/java/com/agileboot/admin/controller/system/SysNoticeController.java b/agileboot-admin/src/main/java/com/agileboot/admin/controller/system/SysNoticeController.java index c11b87d..35c8c2a 100644 --- a/agileboot-admin/src/main/java/com/agileboot/admin/controller/system/SysNoticeController.java +++ b/agileboot-admin/src/main/java/com/agileboot/admin/controller/system/SysNoticeController.java @@ -11,6 +11,7 @@ import com.agileboot.domain.system.notice.dto.NoticeDTO; import com.agileboot.domain.system.notice.query.NoticeQuery; import com.agileboot.infrastructure.annotations.AccessLog; import com.agileboot.infrastructure.annotations.Unrepeatable; +import com.agileboot.infrastructure.annotations.Unrepeatable.CheckType; import com.agileboot.orm.common.enums.BusinessTypeEnum; import com.baomidou.dynamic.datasource.annotation.DS; import io.swagger.v3.oas.annotations.Operation; @@ -85,7 +86,7 @@ public class SysNoticeController extends BaseController { * 新增通知公告 */ @Operation(summary = "添加公告") - @Unrepeatable(interval = 60) + @Unrepeatable(interval = 60, checkType = CheckType.WEB_USER) @PreAuthorize("@permission.has('system:notice:add')") @AccessLog(title = "通知公告", businessType = BusinessTypeEnum.ADD) @PostMapping diff --git a/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/annotations/RateLimit.java b/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/annotations/RateLimit.java index a8b7370..45ca151 100644 --- a/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/annotations/RateLimit.java +++ b/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/annotations/RateLimit.java @@ -72,12 +72,26 @@ public @interface RateLimit { }, /** - * 按用户限流 + * 按Web用户限流 */ - USER { + WEB_USER { @Override public String generateCombinedKey(RateLimit rateLimiter) { - LoginUser loginUser = AuthenticationUtils.getLoginUser(); + LoginUser loginUser = AuthenticationUtils.getWebLoginUser(); + if (loginUser == null) { + throw new ApiException(ErrorCode.Client.COMMON_NO_AUTHORIZATION); + } + return rateLimiter.key() + loginUser.getUsername(); + } + }, + + /** + * 按App用户限流 + */ + APP_USER { + @Override + public String generateCombinedKey(RateLimit rateLimiter) { + LoginUser loginUser = AuthenticationUtils.getAppLoginUser(); if (loginUser == null) { throw new ApiException(ErrorCode.Client.COMMON_NO_AUTHORIZATION); } @@ -85,6 +99,7 @@ public @interface RateLimit { } }; + public abstract String generateCombinedKey(RateLimit rateLimiter); } diff --git a/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/annotations/Unrepeatable.java b/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/annotations/Unrepeatable.java index a3341f8..79d0ab0 100644 --- a/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/annotations/Unrepeatable.java +++ b/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/annotations/Unrepeatable.java @@ -1,11 +1,16 @@ package com.agileboot.infrastructure.annotations; +import cn.hutool.core.util.StrUtil; +import com.agileboot.infrastructure.security.AuthenticationUtils; +import com.agileboot.infrastructure.web.domain.login.LoginUser; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.reflect.Method; +import lombok.extern.slf4j.Slf4j; /** * 自定义注解防止表单重复提交 @@ -23,4 +28,67 @@ public @interface Unrepeatable { */ int interval() default 5; + // TODO改成和rate limit一样 可以选择类型 + + /** + * 检测条件类型 + */ + CheckType checkType() default CheckType.WEB_USER; + + @Slf4j + enum CheckType { + /** + * 按App用户 + */ + APP_USER { + @Override + public String generateResubmitRedisKey(Method method) { + String username; + + try { + LoginUser loginUser = AuthenticationUtils.getAppLoginUser(); + username = loginUser.getUsername(); + } catch (Exception e) { + username = NO_LOGIN; + log.error("could not find the related user to check repeatable submit."); + } + + return StrUtil.format(RESUBMIT_REDIS_KEY, + this.name(), + method.getDeclaringClass().getName(), + method.getName(), + username); + } + }, + /** + * 按Web用户 + */ + WEB_USER { + @Override + public String generateResubmitRedisKey(Method method) { + String username; + + try { + LoginUser loginUser = AuthenticationUtils.getWebLoginUser(); + username = loginUser.getUsername(); + } catch (Exception e) { + username = NO_LOGIN; + log.error("could not find the related user to check repeatable submit."); + } + + return StrUtil.format(RESUBMIT_REDIS_KEY, + this.name(), + method.getDeclaringClass().getName(), + method.getName(), + username); + } + }; + + public static final String NO_LOGIN = "Anonymous"; + public static final String RESUBMIT_REDIS_KEY = "resubmit:{}:{}:{}:{}"; + + public abstract String generateResubmitRedisKey(Method method); + + } + } diff --git a/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/interceptor/repeatsubmit/ResubmitInterceptor.java b/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/interceptor/repeatsubmit/ResubmitInterceptor.java index afe20a6..eb3a82f 100644 --- a/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/interceptor/repeatsubmit/ResubmitInterceptor.java +++ b/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/interceptor/repeatsubmit/ResubmitInterceptor.java @@ -56,7 +56,7 @@ public class ResubmitInterceptor extends RequestBodyAdviceAdapter { Unrepeatable resubmitAnno = parameter.getMethodAnnotation(Unrepeatable.class); if (resubmitAnno != null) { - String redisKey = generateResubmitRedisKey(parameter.getMethod()); + String redisKey = resubmitAnno.checkType().generateResubmitRedisKey(parameter.getMethod()); log.info("请求重复提交拦截,当前key:{}, 当前参数:{}", redisKey, currentRequest); @@ -74,20 +74,4 @@ public class ResubmitInterceptor extends RequestBodyAdviceAdapter { return body; } - public String generateResubmitRedisKey(Method method) { - String username; - - try { - LoginUser loginUser = AuthenticationUtils.getLoginUser(); - username = loginUser.getUsername(); - } catch (Exception e) { - log.warn("未找到对象用户", e); - username = NO_LOGIN; - } - - return StrUtil.format(RESUBMIT_REDIS_KEY, - method.getDeclaringClass().getName(), - method.getName(), - username); - } } diff --git a/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/security/AuthenticationUtils.java b/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/security/AuthenticationUtils.java index f0a73dc..2cb4449 100644 --- a/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/security/AuthenticationUtils.java +++ b/agileboot-infrastructure/src/main/java/com/agileboot/infrastructure/security/AuthenticationUtils.java @@ -39,6 +39,28 @@ public class AuthenticationUtils { } } + /** + * 获取App用户 + **/ + public static LoginUser getAppLoginUser() { + try { + return (LoginUser) getAuthentication().getPrincipal(); + } catch (Exception e) { + throw new ApiException(ErrorCode.Business.USER_FAIL_TO_GET_USER_INFO); + } + } + + /** + * 获取App用户 + **/ + public static LoginUser getWebLoginUser() { + try { + return (LoginUser) getAuthentication().getPrincipal(); + } catch (Exception e) { + throw new ApiException(ErrorCode.Business.USER_FAIL_TO_GET_USER_INFO); + } + } + /** * 获取Authentication */