131 lines
5.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.designhub.controller;
import com.designhub.common.Result;
import com.designhub.dto.LoginDTO;
import com.designhub.dto.RegisterDTO;
import com.designhub.entity.User;
import com.designhub.exception.BusinessException;
import com.designhub.service.UserService;
import com.designhub.util.JwtUtil;
import com.designhub.vo.LoginVO;
import com.designhub.vo.UserInfoVO;
import io.swagger.v3.oas.annotations.Operation;
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.*;
import java.util.HashMap;
import java.util.Map;
/**
* 认证控制器
*/
@Slf4j
@Tag(name = "用户认证", description = "用户登录、登出、刷新令牌等接口")
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {
private final UserService userService;
private final JwtUtil jwtUtil;
@Operation(summary = "用户注册", description = "新用户注册")
@PostMapping("/register")
public Result<User> register(@Valid @RequestBody RegisterDTO registerDTO) {
log.info("用户注册请求: {}", registerDTO.getUsername());
User user = userService.register(registerDTO);
return Result.success(user);
}
@Operation(summary = "用户登录", description = "支持密码登录、钉钉登录、Casdoor登录")
@PostMapping("/login")
public Result<LoginVO> login(@Valid @RequestBody LoginDTO loginDTO) {
log.info("用户登录请求: {}", loginDTO.getUsername());
LoginVO loginVO = userService.login(loginDTO);
return Result.success(loginVO);
}
@Operation(summary = "获取当前用户信息", description = "根据Token获取当前登录用户信息")
@GetMapping("/userinfo")
public Result<UserInfoVO> getUserInfo(@RequestHeader(value = "Authorization", required = false) String authHeader) {
log.info("获取用户信息");
String token = jwtUtil.extractTokenFromHeader(authHeader);
UserInfoVO userInfo = userService.getUserInfoByToken(token);
return Result.success(userInfo);
}
@Operation(summary = "用户登出", description = "退出登录,清除Token")
@PostMapping("/logout")
public Result<String> logout(@RequestHeader(value = "Authorization", required = false) String authHeader) {
log.info("用户登出");
// Token是无状态的,前端删除即可
// 如果需要黑名单机制,可以在Redis中记录
return Result.success("登出成功");
}
@Operation(summary = "刷新令牌", description = "使用刷新令牌获取新的访问令牌")
@PostMapping("/refresh")
public Result<LoginVO> refresh(@RequestHeader("Authorization") String authHeader) {
log.info("刷新令牌");
LoginVO loginVO = userService.refreshToken(authHeader);
return Result.success(loginVO);
}
@Operation(summary = "钉钉扫码登录回调", description = "接收钉钉扫码登录的回调 - 使用OAuth 2.0流程")
@GetMapping("/dingtalk/callback")
@SuppressWarnings("unchecked")
public Result<LoginVO> dingtalkCallback(
@RequestParam String code,
@RequestParam(required = false) String state) {
log.info("钉钉登录回调 - code: {}, state: {}",
code.substring(0, Math.min(10, code.length())) + "...", state);
// 使用新的OAuth 2.0流程登录
LoginDTO loginDTO = new LoginDTO();
loginDTO.setLoginType("dingtalk");
loginDTO.setAuthCode(code);
try {
LoginVO loginVO = userService.login(loginDTO);
log.info("钉钉登录成功: {}", loginVO.getUsername());
return Result.success(loginVO);
} catch (BusinessException e) {
// 检查是否需要选择部门
if (e.getMessage() != null && e.getMessage().startsWith("NEED_SELECT_DEPT:")) {
String[] parts = e.getMessage().split(":");
Map<String, Object> data = new HashMap<>();
data.put("needSelectDept", true);
data.put("userId", parts[1]);
data.put("dingDepartments", parts.length > 2 ? parts[2] : "");
Result<Map<String, Object>> result = Result.error(1901, "需要选择部门", data);
return (Result<LoginVO>) (Result<?>) result;
}
log.error("钉钉登录失败", e);
return Result.error(e.getMessage());
} catch (Exception e) {
log.error("钉钉登录失败", e);
return Result.error("钉钉登录失败: " + e.getMessage());
}
}
@Operation(summary = "钉钉用户选择部门", description = "首次登录时选择系统部门")
@PostMapping("/dingtalk/select-department")
public Result<LoginVO> selectDepartment(
@RequestParam Long userId,
@RequestParam Long deptId) {
log.info("钉钉用户选择部门: userId={}, deptId={}", userId, deptId);
try {
LoginVO loginVO = userService.completeDingTalkUserSetup(userId, deptId);
return Result.success(loginVO);
} catch (Exception e) {
log.error("选择部门失败", e);
return Result.error("选择部门失败: " + e.getMessage());
}
}
}