From 81870bd80264661994c5d580c12cdf84a672fb7d Mon Sep 17 00:00:00 2001 From: none Date: Fri, 10 Mar 2023 14:24:36 +0800 Subject: [PATCH] =?UTF-8?q?=E7=99=BB=E5=BD=95=E5=A2=9E=E5=8A=A0=E9=99=90?= =?UTF-8?q?=E6=B5=81=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../playedu/api/caches/UserLoginCache.java | 32 +++++++++++++++++++ .../api/controller/ExceptionController.java | 6 ++++ .../controller/frontend/LoginController.java | 14 ++++++-- .../xyz/playedu/api/event/UserLoginEvent.java | 5 ++- .../playedu/api/exception/LimitException.java | 26 +++++++++++++++ .../api/listener/UserLoginListener.java | 9 ++++++ .../java/xyz/playedu/api/util/RedisUtil.java | 1 - 7 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 src/main/java/xyz/playedu/api/caches/UserLoginCache.java create mode 100644 src/main/java/xyz/playedu/api/exception/LimitException.java diff --git a/src/main/java/xyz/playedu/api/caches/UserLoginCache.java b/src/main/java/xyz/playedu/api/caches/UserLoginCache.java new file mode 100644 index 0000000..0ff081f --- /dev/null +++ b/src/main/java/xyz/playedu/api/caches/UserLoginCache.java @@ -0,0 +1,32 @@ +package xyz.playedu.api.caches; + +import org.springframework.stereotype.Component; +import xyz.playedu.api.exception.LimitException; +import xyz.playedu.api.util.RedisUtil; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/3/10 14:13 + */ +@Component +public class UserLoginCache { + + private final static String keyTemplate = "user-login:%s"; + + private final static int expire = 10;//10s + + public void check(String email) throws LimitException { + if (RedisUtil.exists(key(email))) { + throw new LimitException(); + } + } + + public void put(String email) { + RedisUtil.set(key(email), "1", expire); + } + + private String key(String email) { + return String.format(keyTemplate, email); + } + +} diff --git a/src/main/java/xyz/playedu/api/controller/ExceptionController.java b/src/main/java/xyz/playedu/api/controller/ExceptionController.java index 60df195..17c95a8 100644 --- a/src/main/java/xyz/playedu/api/controller/ExceptionController.java +++ b/src/main/java/xyz/playedu/api/controller/ExceptionController.java @@ -9,6 +9,7 @@ import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; +import xyz.playedu.api.exception.LimitException; import xyz.playedu.api.exception.NotFoundException; import xyz.playedu.api.exception.ServiceException; import xyz.playedu.api.types.JsonResponse; @@ -66,4 +67,9 @@ public class ExceptionController { return JsonResponse.error(e.getMessage(), 404); } + @ExceptionHandler(LimitException.class) + public JsonResponse serviceExceptionHandler(LimitException e) { + return JsonResponse.error("请稍后再试", 429); + } + } diff --git a/src/main/java/xyz/playedu/api/controller/frontend/LoginController.java b/src/main/java/xyz/playedu/api/controller/frontend/LoginController.java index 2f6222c..14cfa31 100644 --- a/src/main/java/xyz/playedu/api/controller/frontend/LoginController.java +++ b/src/main/java/xyz/playedu/api/controller/frontend/LoginController.java @@ -7,9 +7,11 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import xyz.playedu.api.caches.UserLoginCache; import xyz.playedu.api.constant.SystemConstant; import xyz.playedu.api.domain.User; import xyz.playedu.api.event.UserLoginEvent; +import xyz.playedu.api.exception.LimitException; import xyz.playedu.api.request.frontend.LoginPasswordRequest; import xyz.playedu.api.service.JWTService; import xyz.playedu.api.service.UserService; @@ -39,9 +41,15 @@ public class LoginController { @Autowired private ApplicationContext ctx; + @Autowired + private UserLoginCache userLoginCache; + @PostMapping("/password") - public JsonResponse password(@RequestBody @Validated LoginPasswordRequest req) { - User user = userService.find(req.getEmail()); + public JsonResponse password(@RequestBody @Validated LoginPasswordRequest req) throws LimitException { + String email = req.getEmail(); + userLoginCache.check(email); + + User user = userService.find(email); if (user == null) { return JsonResponse.error("邮箱未注册"); } @@ -55,7 +63,7 @@ public class LoginController { data.put("token", token.getToken()); data.put("expired", token.getExpire()); - ctx.publishEvent(new UserLoginEvent(this, user.getId(), new Date(), token.getToken(), IpUtil.getIpAddress(), RequestUtil.ua())); + ctx.publishEvent(new UserLoginEvent(this, user.getId(), user.getEmail(), new Date(), token.getToken(), IpUtil.getIpAddress(), RequestUtil.ua())); return JsonResponse.data(data); } diff --git a/src/main/java/xyz/playedu/api/event/UserLoginEvent.java b/src/main/java/xyz/playedu/api/event/UserLoginEvent.java index 4a11162..c204f47 100644 --- a/src/main/java/xyz/playedu/api/event/UserLoginEvent.java +++ b/src/main/java/xyz/playedu/api/event/UserLoginEvent.java @@ -17,6 +17,8 @@ public class UserLoginEvent extends ApplicationEvent { private Integer userId; + private String email; + private Date loginAt; private String token; @@ -25,9 +27,10 @@ public class UserLoginEvent extends ApplicationEvent { private UserAgent userAgent; - public UserLoginEvent(Object source, Integer userId, Date loginAt, String token, String ip, UserAgent userAgent) { + public UserLoginEvent(Object source, Integer userId,String email, Date loginAt, String token, String ip, UserAgent userAgent) { super(source); this.userId = userId; + this.email = email; this.loginAt = loginAt; this.token = token; this.ip = ip; diff --git a/src/main/java/xyz/playedu/api/exception/LimitException.java b/src/main/java/xyz/playedu/api/exception/LimitException.java new file mode 100644 index 0000000..a2f26f2 --- /dev/null +++ b/src/main/java/xyz/playedu/api/exception/LimitException.java @@ -0,0 +1,26 @@ +package xyz.playedu.api.exception; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/3/10 14:13 + */ +public class LimitException extends Exception { + public LimitException() { + } + + public LimitException(String message) { + super(message); + } + + public LimitException(String message, Throwable cause) { + super(message, cause); + } + + public LimitException(Throwable cause) { + super(cause); + } + + public LimitException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/src/main/java/xyz/playedu/api/listener/UserLoginListener.java b/src/main/java/xyz/playedu/api/listener/UserLoginListener.java index 4345fc5..96e0525 100644 --- a/src/main/java/xyz/playedu/api/listener/UserLoginListener.java +++ b/src/main/java/xyz/playedu/api/listener/UserLoginListener.java @@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; +import xyz.playedu.api.caches.UserLoginCache; import xyz.playedu.api.constant.SystemConstant; import xyz.playedu.api.event.UserLoginEvent; import xyz.playedu.api.exception.JwtLogoutException; @@ -27,6 +28,9 @@ public class UserLoginListener { @Autowired private JWTService jwtService; + @Autowired + private UserLoginCache userLoginCache; + @EventListener @Async public void updateLoginInfo(UserLoginEvent event) throws JwtLogoutException { @@ -44,4 +48,9 @@ public class UserLoginListener { ); } + @EventListener + public void writeCache(UserLoginEvent event) { + userLoginCache.put(event.getEmail()); + } + } diff --git a/src/main/java/xyz/playedu/api/util/RedisUtil.java b/src/main/java/xyz/playedu/api/util/RedisUtil.java index 35286c4..71631ed 100644 --- a/src/main/java/xyz/playedu/api/util/RedisUtil.java +++ b/src/main/java/xyz/playedu/api/util/RedisUtil.java @@ -8,7 +8,6 @@ import org.springframework.data.redis.core.ScanOptions; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import xyz.playedu.api.config.PlayEduConfig; import xyz.playedu.api.constant.SystemConstant; import java.util.*;