liujie
2026-08-21 ad5db85e540947e82c7a4d5612879b3b3ecdf459
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package com.tourguide.api.guide;
 
import com.tourguide.common.api.ApiResponse;
import com.tourguide.modules.user.domain.ClientType;
import com.tourguide.modules.user.dto.AuthResponse;
import com.tourguide.modules.user.dto.GuidePhoneLoginRequest;
import com.tourguide.modules.user.dto.GuideSmsCodeRequest;
import com.tourguide.modules.user.dto.GuideUserResponse;
import com.tourguide.modules.user.dto.LoginRequest;
import com.tourguide.modules.user.dto.SmsCodeResponse;
import com.tourguide.modules.user.service.AuthService;
import com.tourguide.modules.user.service.GuideAccountService;
import com.tourguide.modules.user.service.GuideVerificationCodeService;
import com.tourguide.security.AppUserPrincipal;
import com.tourguide.security.BearerTokenResolver;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
 
/**
 * 导游端认证接口。
 * 仅签发和接收 GUIDE 客户端类型的 Token,防止导游凭证跨端访问后台或游客接口。
 */
@RestController
@RequestMapping("/api/guide/auth")
public class GuideAuthController {
    private final AuthService authService;
    private final GuideAccountService guideAccountService;
    private final GuideVerificationCodeService verificationCodeService;
    private final BearerTokenResolver tokenResolver;
 
    public GuideAuthController(AuthService authService, GuideAccountService guideAccountService,
                               GuideVerificationCodeService verificationCodeService,
                               BearerTokenResolver tokenResolver) {
        this.authService = authService;
        this.guideAccountService = guideAccountService;
        this.verificationCodeService = verificationCodeService;
        this.tokenResolver = tokenResolver;
    }
 
    /**
     * 使用导游账号和密码登录,校验账号状态后签发 GUIDE Token。
     *
     * @param request 导游登录账号和明文密码
     * @return Token 信息及当前导游基础资料
     */
    @PostMapping("/password-login")
    public ApiResponse<AuthResponse<GuideUserResponse>> passwordLogin(@Valid @RequestBody LoginRequest request) {
        return ApiResponse.success(authService.loginGuide(request));
    }
 
    /** 发送导游手机号登录验证码。 */
    @PostMapping("/sms-code")
    public ApiResponse<SmsCodeResponse> sendSmsCode(@Valid @RequestBody GuideSmsCodeRequest request) {
        authService.ensureGuidePhoneCanLogin(request.getPhone());
        return ApiResponse.success(verificationCodeService.send(request.getPhone()));
    }
 
    /** 校验一次性验证码并签发 GUIDE Token。 */
    @PostMapping("/login")
    public ApiResponse<AuthResponse<GuideUserResponse>> login(@Valid @RequestBody GuidePhoneLoginRequest request) {
        authService.ensureGuidePhoneCanLogin(request.getPhone());
        verificationCodeService.verifyAndConsume(request.getPhone(), request.getCode());
        return ApiResponse.success(authService.loginGuideByPhone(request.getPhone()));
    }
 
    /**
     * 注销当前导游会话,使 Authorization 请求头中的 GUIDE Token 立即失效。
     *
     * @param authorization Bearer Token 请求头
     * @return 无业务数据的成功响应
     */
    @PostMapping("/logout")
    public ApiResponse<Void> logout(@RequestHeader("Authorization") String authorization) {
        authService.logout(tokenResolver.resolve(authorization), ClientType.GUIDE);
        return ApiResponse.success();
    }
 
    /** 注销当前导游账号;存在未完成订单时拒绝注销,并保留后台历史业务资料。 */
    @DeleteMapping("/account")
    public ApiResponse<Void> cancelAccount(@AuthenticationPrincipal AppUserPrincipal principal,
                                           @RequestHeader("Authorization") String authorization) {
        guideAccountService.cancel(principal.getUserId(), tokenResolver.resolve(authorization));
        return ApiResponse.success();
    }
}