Files
youlai-boot/src/main/java/com/youlai/boot/auth/controller/AuthController.java
Ray.Hao b17bd6bf7c refactor(rate-limit): 限流架构升级为双层滑动窗口,新增IP全局防护与响应头
限流算法从 INCR+EXPIRE 固定窗口升级为 ZSET+Lua 滑动窗口,
新增 IpRateLimitFilter 提供 IP 全局防护(默认 1000次/60s)。
新增 X-RateLimit-Limit/Remaining/Reset 响应头与 Retry-After,
新增 rate-limit.ip.* 配置项控制 IP 全局开关与阈值,
@RateLimit 空注解统一走全局配置,消除硬编码。
2026-07-05 00:19:44 +08:00

96 lines
3.5 KiB
Java

package com.youlai.boot.auth.controller;
import com.youlai.boot.auth.model.form.LoginForm;
import com.youlai.boot.common.enums.ActionTypeEnum;
import com.youlai.boot.common.enums.LogModuleEnum;
import com.youlai.boot.common.result.Result;
import com.youlai.boot.auth.service.AuthService;
import com.youlai.boot.common.annotation.Log;
import com.youlai.boot.common.annotation.RateLimit;
import com.youlai.boot.framework.captcha.model.CaptchaInfo;
import com.youlai.boot.framework.security.model.AuthenticationToken;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.DeleteMapping;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 认证控制层
*
* @author Ray.Hao
* @since 0.0.1
*/
@Tag(name = "01.认证中心")
@RestController
@RequestMapping("/api/v1/auth")
@RequiredArgsConstructor
@Slf4j
public class AuthController {
private final AuthService authService;
@Operation(summary = "获取验证码")
@GetMapping("/captcha")
public Result<CaptchaInfo> getCaptcha() {
CaptchaInfo captcha = authService.getCaptcha();
return Result.success(captcha);
}
@Operation(summary = "账号密码登录")
@PostMapping("/login")
@Log(module = LogModuleEnum.LOGIN, value = ActionTypeEnum.LOGIN)
@RateLimit
public Result<AuthenticationToken> login(@RequestBody @Valid LoginForm request) {
AuthenticationToken authenticationToken = authService.login(request.getUsername(), request.getPassword());
return Result.success(authenticationToken);
}
@Operation(summary = "短信验证码登录")
@PostMapping("/login/sms")
@Log(module = LogModuleEnum.LOGIN, value = ActionTypeEnum.LOGIN)
public Result<AuthenticationToken> loginBySms(
@Parameter(description = "手机号", example = "18888888888") @RequestParam String mobile,
@Parameter(description = "验证码", example = "123456") @RequestParam String code
) {
AuthenticationToken loginResult = authService.loginBySms(mobile, code);
return Result.success(loginResult);
}
@Operation(summary = "发送登录短信验证码")
@PostMapping("/sms/code")
@RateLimit(limit = 1, window = 60)
public Result<Void> sendSmsCode(
@Parameter(description = "手机号", example = "18888888888") @RequestParam String mobile
) {
authService.sendSmsCode(mobile);
return Result.success();
}
@Operation(summary = "退出登录")
@DeleteMapping("/logout")
@Log(module = LogModuleEnum.LOGIN, value = ActionTypeEnum.LOGOUT)
public Result<Void> logout() {
authService.logout();
return Result.success();
}
@Operation(summary = "刷新令牌")
@PostMapping("/refresh-token")
public Result<AuthenticationToken> refreshToken(
@Parameter(description = "刷新令牌", example = "xxx.xxx.xxx") @RequestParam String refreshToken
) {
AuthenticationToken authenticationToken = authService.refreshToken(refreshToken);
return Result.success(authenticationToken);
}
}