2026-04-14 13:47:38 +08:00
|
|
|
|
package com.label.controller;
|
2026-04-09 15:16:49 +08:00
|
|
|
|
|
2026-04-14 16:33:34 +08:00
|
|
|
|
import com.label.annotation.RequireAuth;
|
|
|
|
|
|
import com.label.common.auth.TokenPrincipal;
|
2026-04-09 15:16:49 +08:00
|
|
|
|
import com.label.common.result.Result;
|
2026-04-14 13:39:24 +08:00
|
|
|
|
import com.label.dto.LoginRequest;
|
|
|
|
|
|
import com.label.dto.LoginResponse;
|
|
|
|
|
|
import com.label.dto.UserInfoResponse;
|
2026-04-14 13:45:15 +08:00
|
|
|
|
import com.label.service.AuthService;
|
2026-04-12 00:15:59 +08:00
|
|
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|
|
|
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
2026-04-09 15:16:49 +08:00
|
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-04-14 13:31:50 +08:00
|
|
|
|
* 认证接口:登录、退出、获取当前用户。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 路由设计:
|
2026-04-14 16:33:34 +08:00
|
|
|
|
* - POST /api/auth/login → 匿名(AuthInterceptor 跳过)
|
|
|
|
|
|
* - POST /api/auth/logout → 需要有效 Token(AuthInterceptor 校验)
|
|
|
|
|
|
* - GET /api/auth/me → 需要有效 Token(AuthInterceptor 校验)
|
2026-04-14 13:31:50 +08:00
|
|
|
|
*/
|
|
|
|
|
|
@Tag(name = "认证管理", description = "登录、退出和当前用户信息")
|
2026-04-09 15:16:49 +08:00
|
|
|
|
@RestController
|
2026-04-15 10:46:57 +08:00
|
|
|
|
@RequestMapping("/label/api/auth")
|
2026-04-09 15:16:49 +08:00
|
|
|
|
@RequiredArgsConstructor
|
|
|
|
|
|
public class AuthController {
|
|
|
|
|
|
|
|
|
|
|
|
private final AuthService authService;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-04-14 13:31:50 +08:00
|
|
|
|
* 登录接口(匿名,无需 Token)。
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Operation(summary = "用户登录,返回 Bearer Token")
|
2026-04-09 15:16:49 +08:00
|
|
|
|
@PostMapping("/login")
|
|
|
|
|
|
public Result<LoginResponse> login(@RequestBody LoginRequest request) {
|
|
|
|
|
|
return Result.success(authService.login(request));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-04-14 13:31:50 +08:00
|
|
|
|
* 退出登录,立即删除 Redis Token。
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Operation(summary = "退出登录并立即失效当前 Token")
|
2026-04-09 15:16:49 +08:00
|
|
|
|
@PostMapping("/logout")
|
2026-04-14 16:33:34 +08:00
|
|
|
|
@RequireAuth
|
2026-04-09 15:16:49 +08:00
|
|
|
|
public Result<Void> logout(HttpServletRequest request) {
|
|
|
|
|
|
String token = extractToken(request);
|
|
|
|
|
|
authService.logout(token);
|
|
|
|
|
|
return Result.success(null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-04-14 13:31:50 +08:00
|
|
|
|
* 获取当前登录用户信息。
|
2026-04-14 16:33:34 +08:00
|
|
|
|
* TokenPrincipal 由 AuthInterceptor 写入请求属性 "__token_principal__"。
|
2026-04-14 13:31:50 +08:00
|
|
|
|
*/
|
|
|
|
|
|
@Operation(summary = "获取当前登录用户信息")
|
2026-04-09 15:16:49 +08:00
|
|
|
|
@GetMapping("/me")
|
2026-04-14 16:33:34 +08:00
|
|
|
|
@RequireAuth
|
2026-04-09 15:16:49 +08:00
|
|
|
|
public Result<UserInfoResponse> me(HttpServletRequest request) {
|
|
|
|
|
|
TokenPrincipal principal = (TokenPrincipal) request.getAttribute("__token_principal__");
|
|
|
|
|
|
return Result.success(authService.me(principal));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-14 13:31:50 +08:00
|
|
|
|
/** 从 Authorization 头提取 Bearer token 字符串 */
|
2026-04-09 15:16:49 +08:00
|
|
|
|
private String extractToken(HttpServletRequest request) {
|
|
|
|
|
|
String authHeader = request.getHeader("Authorization");
|
|
|
|
|
|
if (authHeader != null && authHeader.startsWith("Bearer ")) {
|
|
|
|
|
|
return authHeader.substring(7).trim();
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|