From f7a4995c586a67371dcee0b4ab9bff7149f34273 Mon Sep 17 00:00:00 2001 From: LingandRX Date: Tue, 25 Mar 2025 00:52:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(user):=20=E5=AE=9E=E7=8E=B0=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=99=BB=E5=BD=95=E5=92=8C=E8=BA=AB=E4=BB=BD=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增用户登录接口和相关逻辑 - 实现 token 生成和验证功能- 添加用户信息查询接口 - 集成拦截器进行身份验证 - 优化错误处理和提示信息 --- .../copykamanotes/config/WebConfig.java | 27 +++++++++ .../controller/UserController.java | 16 ++++++ .../interceptor/TokenInterceptor.java | 44 +++++++++++++++ .../copykamanotes/mapper/UserMapper.java | 2 + .../service/impl/UserServiceImpl.java | 55 ++++++++++++++++++- .../example/copykamanotes/utils/JwtUtil.java | 2 +- src/main/resources/mapper/UserMapper.xml | 6 ++ 7 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/example/copykamanotes/config/WebConfig.java create mode 100644 src/main/java/com/example/copykamanotes/interceptor/TokenInterceptor.java diff --git a/src/main/java/com/example/copykamanotes/config/WebConfig.java b/src/main/java/com/example/copykamanotes/config/WebConfig.java new file mode 100644 index 0000000..ca84797 --- /dev/null +++ b/src/main/java/com/example/copykamanotes/config/WebConfig.java @@ -0,0 +1,27 @@ +package com.example.copykamanotes.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import com.example.copykamanotes.interceptor.TokenInterceptor; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + @Autowired + private TokenInterceptor tokenInterceptor; + + + /** + * 添加拦截器, 拦截所有请求,除了登录和注册 + * @param registry 拦截器注册器 + */ + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(tokenInterceptor) + .addPathPatterns("/api/**") + .excludePathPatterns("/api/users/login", "/api/users/register"); + } + +} diff --git a/src/main/java/com/example/copykamanotes/controller/UserController.java b/src/main/java/com/example/copykamanotes/controller/UserController.java index 17b4c58..60fe4db 100644 --- a/src/main/java/com/example/copykamanotes/controller/UserController.java +++ b/src/main/java/com/example/copykamanotes/controller/UserController.java @@ -1,7 +1,9 @@ package com.example.copykamanotes.controller; import com.example.copykamanotes.model.base.ApiResponse; +import com.example.copykamanotes.model.dto.user.LoginRequest; import com.example.copykamanotes.model.dto.user.RegisterRequest; +import com.example.copykamanotes.model.vo.user.LoginUserVO; import com.example.copykamanotes.model.vo.user.RegisterVO; import com.example.copykamanotes.service.UserService; import lombok.extern.slf4j.Slf4j; @@ -31,4 +33,18 @@ public class UserController { public ApiResponse hello() { return ApiResponse.success("Hello World"); } + + @PostMapping("/users/login") + public ApiResponse login( + @Valid + @RequestBody + LoginRequest loginRequest + ) { + return userService.login(loginRequest); + } + + @PostMapping("/users/whoami") + public ApiResponse whoami() { + return userService.whoami(); + } } diff --git a/src/main/java/com/example/copykamanotes/interceptor/TokenInterceptor.java b/src/main/java/com/example/copykamanotes/interceptor/TokenInterceptor.java new file mode 100644 index 0000000..2ff072f --- /dev/null +++ b/src/main/java/com/example/copykamanotes/interceptor/TokenInterceptor.java @@ -0,0 +1,44 @@ +package com.example.copykamanotes.interceptor; + +import com.example.copykamanotes.scope.RequestScopeData; +import com.example.copykamanotes.utils.JwtUtil; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +@Component +public class TokenInterceptor implements HandlerInterceptor { + + @Autowired + private RequestScopeData requestScopeData; + + @Autowired + private JwtUtil jwtUtil; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String token = request.getHeader("Authorization"); + + if (token == null) { + requestScopeData.setLogin(false); + requestScopeData.setUserId(null); + requestScopeData.setUserId(null); + return true; + } + + token = token.replace("Bearer ", ""); + + if (!jwtUtil.validateToken(token)) { + Long userId = jwtUtil.getUserIdFromToken(token); + requestScopeData.setUserId(userId); + requestScopeData.setToken(token); + requestScopeData.setLogin(true); + } else { + requestScopeData.setLogin(false); + } + return HandlerInterceptor.super.preHandle(request, response, handler); + } +} diff --git a/src/main/java/com/example/copykamanotes/mapper/UserMapper.java b/src/main/java/com/example/copykamanotes/mapper/UserMapper.java index 2827c5e..cf6de15 100644 --- a/src/main/java/com/example/copykamanotes/mapper/UserMapper.java +++ b/src/main/java/com/example/copykamanotes/mapper/UserMapper.java @@ -18,4 +18,6 @@ public interface UserMapper { User findByEmail(@Param("email") String email); int updateLastLoginAt(@Param("userId") Long userId); + + User findById(@Param("userId") Long userId); } diff --git a/src/main/java/com/example/copykamanotes/service/impl/UserServiceImpl.java b/src/main/java/com/example/copykamanotes/service/impl/UserServiceImpl.java index aaa6bbe..bfac14d 100644 --- a/src/main/java/com/example/copykamanotes/service/impl/UserServiceImpl.java +++ b/src/main/java/com/example/copykamanotes/service/impl/UserServiceImpl.java @@ -15,6 +15,7 @@ import com.example.copykamanotes.service.EmailService; import com.example.copykamanotes.service.UserService; import com.example.copykamanotes.utils.ApiResponseUtil; import com.example.copykamanotes.utils.JwtUtil; +import com.google.protobuf.Api; import lombok.extern.log4j.Log4j2; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -86,18 +87,66 @@ public class UserServiceImpl implements UserService { return ApiResponseUtil.success("注册成功", registerVO, token); } catch (Exception e) { log.error("注册失败", e); - return ApiResponseUtil.error("注册失败"); + return ApiResponseUtil.error("注册失败,请稍后再试"); } } @Override public ApiResponse login(LoginRequest loginRequest) { - return null; + User user = null; + + if (loginRequest.getAccount() != null && !loginRequest.getAccount().isEmpty()) { + user = userMapper.findByAccount(loginRequest.getAccount()); + } else if (loginRequest.getEmail() != null && !loginRequest.getEmail().isEmpty()) { + user = userMapper.findByEmail(loginRequest.getEmail()); + } else { + return ApiResponseUtil.error("账号或邮箱不能为空"); + } + + if (user == null) { + return ApiResponseUtil.error("账号或邮箱不存在"); + } + + if (!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword())) { + return ApiResponseUtil.error("密码错误"); + } + + String token = jwtUtil.generateToken(user.getUserId()); + + LoginUserVO loginUserVO = new LoginUserVO(); + BeanUtils.copyProperties(user, loginUserVO); + + userMapper.updateLastLoginAt(user.getUserId()); + + return ApiResponseUtil.success("登录成功", loginUserVO, token); } @Override public ApiResponse whoami() { - return null; + Long userId = requestScopeData.getUserId(); + + if (userId == null) { + return ApiResponseUtil.error("未登录"); + } + + try { + User user = userMapper.findById(userId); + if (user == null) { + return ApiResponseUtil.error("用户不存在"); + } + + String newToken = jwtUtil.generateToken(userId); + if (newToken == null) { + return ApiResponseUtil.error("token生成失败"); + } + + LoginUserVO loginUserVO = new LoginUserVO(); + BeanUtils.copyProperties(user, loginUserVO); + return ApiResponseUtil.success("获取用户信息成功", loginUserVO, newToken); + } catch (Exception e) { + log.error("获取用户信息失败", e); + return ApiResponseUtil.error("获取用户信息失败"); + } } @Override diff --git a/src/main/java/com/example/copykamanotes/utils/JwtUtil.java b/src/main/java/com/example/copykamanotes/utils/JwtUtil.java index 899b8b8..8c7d3af 100644 --- a/src/main/java/com/example/copykamanotes/utils/JwtUtil.java +++ b/src/main/java/com/example/copykamanotes/utils/JwtUtil.java @@ -45,7 +45,7 @@ public class JwtUtil { public Long getUserIdFromToken(String token) { try { Claims claims = Jwts.parser() - .setSigningKey(secret) + .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); return Long.valueOf(claims.get("userId").toString()); diff --git a/src/main/resources/mapper/UserMapper.xml b/src/main/resources/mapper/UserMapper.xml index ec11871..46ffe1d 100644 --- a/src/main/resources/mapper/UserMapper.xml +++ b/src/main/resources/mapper/UserMapper.xml @@ -31,6 +31,12 @@ NOW()) + +