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

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");
}
}