You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
5.0 KiB
109 lines
5.0 KiB
package com.mydreamjob.controller;
|
|
|
|
import com.mydreamjob.auth.AuthService;
|
|
import com.mydreamjob.auth.JwtTokenProvider;
|
|
import com.mydreamjob.auth.LoginRequest;
|
|
import com.mydreamjob.auth.SmsVerificationService;
|
|
import com.mydreamjob.common.api.ApiResponse;
|
|
import com.mydreamjob.common.exception.BusinessException;
|
|
import com.mydreamjob.common.exception.ErrorCode;
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
import jakarta.validation.ConstraintViolationException;
|
|
import jakarta.validation.Valid;
|
|
import jakarta.validation.constraints.NotBlank;
|
|
import jakarta.validation.constraints.Pattern;
|
|
import lombok.RequiredArgsConstructor;
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.security.core.Authentication;
|
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
import org.springframework.validation.annotation.Validated;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* 认证相关接口
|
|
*/
|
|
@Tag(name = "认证", description = "登录、验证码、用户信息")
|
|
@RestController
|
|
@RequestMapping("/auth")
|
|
@RequiredArgsConstructor
|
|
@Validated
|
|
public class AuthController {
|
|
|
|
private final AuthService authService;
|
|
private final SmsVerificationService smsVerificationService;
|
|
private final JwtTokenProvider jwtTokenProvider;
|
|
|
|
@Operation(summary = "发送短信验证码", description = "开发/测试使用 Mock 发送实现;生产环境未接入短信网关时返回服务不可用。验证码不会写入日志。")
|
|
@PostMapping("/sms/send")
|
|
public ResponseEntity<ApiResponse<Map<String, String>>> sendSmsCode(
|
|
@RequestParam @NotBlank(message = "phone is required")
|
|
@Pattern(regexp = "[0-9]{11}", message = "phone must contain exactly 11 digits") String phone,
|
|
@RequestParam(defaultValue = "login") String purpose,
|
|
HttpServletRequest request) {
|
|
try {
|
|
smsVerificationService.sendCode(phone, purpose,
|
|
getRequestId(request),
|
|
request.getRemoteAddr(),
|
|
request.getHeader("User-Agent"));
|
|
return ResponseEntity.ok(ApiResponse.ok(
|
|
Map.of("message", "验证码已发送(Mock)"),
|
|
getRequestId(request)));
|
|
} catch (ConstraintViolationException e) {
|
|
return ResponseEntity.badRequest().body(
|
|
ApiResponse.badRequest(e.getMessage(), getRequestId(request)));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.badRequest().body(
|
|
ApiResponse.error(400, e.getMessage(), getRequestId(request)));
|
|
}
|
|
}
|
|
|
|
@Operation(summary = "Mock 登录", description = "使用手机号+验证码登录,返回 JWT token")
|
|
@PostMapping("/login")
|
|
public ResponseEntity<ApiResponse<Map<String, Object>>> mockLogin(
|
|
@Valid @RequestBody LoginRequest body,
|
|
HttpServletRequest request) {
|
|
String phone = body.getPhone();
|
|
String code = body.getCode();
|
|
String purpose = body.getPurpose() == null || body.getPurpose().isBlank()
|
|
? "login" : body.getPurpose();
|
|
try {
|
|
Map<String, Object> result = authService.mockLogin(phone, code, purpose,
|
|
getRequestId(request),
|
|
request.getRemoteAddr(),
|
|
request.getHeader("User-Agent"));
|
|
return ResponseEntity.ok(ApiResponse.ok(result, getRequestId(request)));
|
|
} catch (BusinessException e) {
|
|
// 已注销手机号:保留 HTTP 409 / 业务 code=9303,交由全局异常处理器映射。
|
|
// 其余业务异常(如验证码错误、参数校验)维持既有 400/code=400 行为。
|
|
if (e.getErrorCodeInt() == ErrorCode.ACCOUNT_DELETED.getCode()) {
|
|
throw e;
|
|
}
|
|
return ResponseEntity.badRequest().body(
|
|
ApiResponse.error(400, e.getMessage(), getRequestId(request)));
|
|
} catch (Exception e) {
|
|
return ResponseEntity.badRequest().body(
|
|
ApiResponse.error(400, e.getMessage(), getRequestId(request)));
|
|
}
|
|
}
|
|
|
|
@Operation(summary = "当前用户信息", description = "需要 JWT 认证")
|
|
@GetMapping("/me")
|
|
public ResponseEntity<ApiResponse<Map<String, Object>>> me(HttpServletRequest request) {
|
|
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
|
if (auth == null || !auth.isAuthenticated()) {
|
|
return ResponseEntity.status(401).body(
|
|
ApiResponse.unauthorized("not authenticated", getRequestId(request)));
|
|
}
|
|
Long userId = Long.valueOf(auth.getName());
|
|
return ResponseEntity.ok(ApiResponse.ok(authService.getCurrentUser(userId), getRequestId(request)));
|
|
}
|
|
|
|
private String getRequestId(HttpServletRequest request) {
|
|
return request.getHeader("X-Request-Id");
|
|
}
|
|
}
|
|
|