diff --git a/pom.xml b/pom.xml
index 84953e0..7abf7f3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,16 +35,26 @@
21
+ 2025.0.0
-
- org.springframework.boot
- spring-boot-starter-data-redis-reactive
-
+
+
+
+
+
+
+
+
+
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.boot
+ spring-boot-starter-data-redis-reactive
+
org.springframework.boot
spring-boot-starter-jdbc
@@ -148,7 +158,6 @@
3.1.499
-
diff --git a/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java b/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java
index 84df6ac..b535a90 100644
--- a/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java
+++ b/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java
@@ -27,6 +27,7 @@ public class SecurityConfig {
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
+ .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
);
return http.build();
diff --git a/src/main/java/com/onekeycall/videotablet/controller/LoginController.java b/src/main/java/com/onekeycall/videotablet/controller/LoginController.java
index c0b06ee..8b26b7e 100644
--- a/src/main/java/com/onekeycall/videotablet/controller/LoginController.java
+++ b/src/main/java/com/onekeycall/videotablet/controller/LoginController.java
@@ -5,7 +5,6 @@ import com.onekeycall.videotablet.entity.User;
import com.onekeycall.videotablet.result.Result;
import com.onekeycall.videotablet.service.UserService;
import com.onekeycall.videotablet.utils.JwtUtil;
-import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
@@ -15,14 +14,12 @@ import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
+@RequestMapping("/public")
public class LoginController {
private final UserService userService;
@@ -39,7 +36,7 @@ public class LoginController {
this.authenticationManager = authenticationManager;
}
- @PostMapping("/public/register")
+ @PostMapping("/register")
public ResponseEntity> registerUser(@RequestBody RegisterRequest registerRequest) {
try {
userService.registerUser(registerRequest.getUsername(), registerRequest.getPassword());
@@ -49,7 +46,7 @@ public class LoginController {
}
}
- @PostMapping("/public/login")
+ @PostMapping("/login")
public ResponseEntity> login(
@RequestParam(value = "user_id") String userId, @RequestParam String password,
@RequestParam(value = "device_id", required = false) String deviceId) {
@@ -91,7 +88,7 @@ public class LoginController {
}
- @PostMapping("/public/registerByPhone")
+ @PostMapping("/phone_register")
public Result registerByPhone(
@RequestParam String phone, @RequestParam String code,
@RequestParam(value = "verify_key") String verifyKey, @RequestParam(value = "device_id") String deviceId) {
@@ -129,7 +126,7 @@ public class LoginController {
}
}
- @PostMapping("/public/loginByPhone")
+ @PostMapping("/phone_login")
public Result loginByPhone(
@RequestParam String phone, @RequestParam String code,
@RequestParam(value = "verify_key") String verifyKey, @RequestParam(value = "device_id") String deviceId) {
@@ -161,54 +158,5 @@ public class LoginController {
}
}
- @PostMapping("/public/setPasswordByPhone")
- public Result setPasswordByPhone(
- HttpServletRequest request, @RequestParam(value = "user_id") String userId,
- @RequestParam String password, @RequestParam(value = "verify_password") String verifyPassword,
- @RequestParam(value = "device_id") String deviceId) {
- String authHeader = request.getHeader("Authorization");
- if (authHeader != null && authHeader.startsWith("Bearer ")) {
- String token = authHeader.substring(7); // 提取真正的Token
- if (StringUtils.equals(password, verifyPassword)) {
- if (jwtUtil.validateAccessToken(userId, token, deviceId)) {
- userService.setPasswordByUserId(userId, password);
- return Result.ok().message("set password success");
- } else {
- return Result.error().message("token is not same");
- }
- } else {
- return Result.error().message("password is not same");
- }
- } else {
- return Result.error().message("Authorization header is incorrect");
- }
- }
- @PostMapping("/public/changePassword")
- public Result changePassword(
- HttpServletRequest request,
- @RequestParam(value = "user_id") String userId,
- @RequestParam(value = "old_password") String oldPassword,
- @RequestParam String password, @RequestParam(value = "verify_password") String verifyPassword,
- @RequestParam(value = "device_id") String deviceId) {
- String authHeader = request.getHeader("Authorization");
- if (authHeader != null && authHeader.startsWith("Bearer ")) {
- String token = authHeader.substring(7);
- if (StringUtils.equals(password, verifyPassword)) {
- if (!oldPassword.equals(password)) {
- if (jwtUtil.validateAccessToken(userId, token, deviceId)) {
- return userService.changePassword(userId, oldPassword, password);
- } else {
- return Result.error().message("token is not same");
- }
- } else {
- return Result.error().message("The old password and the new password are the same");
- }
- } else {
- return Result.error().message("password is not same");
- }
- } else {
- return Result.error().message("Authorization header is incorrect");
- }
- }
}
\ No newline at end of file
diff --git a/src/main/java/com/onekeycall/videotablet/controller/UserPasswordController.java b/src/main/java/com/onekeycall/videotablet/controller/UserPasswordController.java
new file mode 100644
index 0000000..7d788dc
--- /dev/null
+++ b/src/main/java/com/onekeycall/videotablet/controller/UserPasswordController.java
@@ -0,0 +1,83 @@
+package com.onekeycall.videotablet.controller;
+
+import com.onekeycall.videotablet.result.Result;
+import com.onekeycall.videotablet.service.UserService;
+import com.onekeycall.videotablet.utils.JwtUtil;
+import jakarta.servlet.http.HttpServletRequest;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/user")
+public class UserPasswordController {
+ private final UserService userService;
+ private final AuthenticationManager authenticationManager;
+
+ @Autowired
+ private RedisTemplate redisTemplate;
+ @Autowired
+ private JwtUtil jwtUtil;
+
+ @Autowired
+ public UserPasswordController(UserService userService, AuthenticationManager authenticationManager) {
+ this.userService = userService;
+ this.authenticationManager = authenticationManager;
+ }
+
+ @PostMapping("/phone_set_password")
+ public Result setPasswordByPhone(
+ HttpServletRequest request, @RequestParam(value = "user_id") String userId,
+ @RequestParam String password, @RequestParam(value = "verify_password") String verifyPassword,
+ @RequestParam(value = "device_id") String deviceId) {
+ String authHeader = request.getHeader("Authorization");
+ if (authHeader != null && authHeader.startsWith("Bearer ")) {
+ String token = authHeader.substring(7); // 提取真正的Token
+ if (StringUtils.equals(password, verifyPassword)) {
+ if (jwtUtil.validateAccessToken(userId, token, deviceId)) {
+ userService.setPasswordByUserId(userId, password);
+ return Result.ok().message("set password success");
+ } else {
+ return Result.error().message("token is not same");
+ }
+ } else {
+ return Result.error().message("password is not same");
+ }
+ } else {
+ return Result.error().message("Authorization header is incorrect");
+ }
+ }
+
+ @PostMapping("/change_password")
+ public Result changePassword(
+ HttpServletRequest request,
+ @RequestParam(value = "user_id") String userId,
+ @RequestParam(value = "old_password") String oldPassword,
+ @RequestParam String password, @RequestParam(value = "verify_password") String verifyPassword,
+ @RequestParam(value = "device_id") String deviceId) {
+ String authHeader = request.getHeader("Authorization");
+ if (authHeader != null && authHeader.startsWith("Bearer ")) {
+ String token = authHeader.substring(7);
+ if (StringUtils.equals(password, verifyPassword)) {
+ if (!oldPassword.equals(password)) {
+ if (jwtUtil.validateAccessToken(userId, token, deviceId)) {
+ return userService.changePassword(userId, oldPassword, password);
+ } else {
+ return Result.error().message("token is not same");
+ }
+ } else {
+ return Result.error().message("The old password and the new password are the same");
+ }
+ } else {
+ return Result.error().message("password is not same");
+ }
+ } else {
+ return Result.error().message("Authorization header is incorrect");
+ }
+ }
+}
diff --git a/src/main/java/com/onekeycall/videotablet/entity/User.java b/src/main/java/com/onekeycall/videotablet/entity/User.java
index a407caf..b70702c 100644
--- a/src/main/java/com/onekeycall/videotablet/entity/User.java
+++ b/src/main/java/com/onekeycall/videotablet/entity/User.java
@@ -9,12 +9,12 @@ import java.util.Collections;
import java.util.Date;
@Entity
-@Table(name = "users")
+@Table(name = "ordinary_users")
public class User implements UserDetails {
@Transient // 关键注解:声明此字段不映射到数据库
private boolean newUser;
- @Transient // 关键注解:声明此字段不映射到数据库
+ @Transient
private boolean hasPassword;
@Id
diff --git a/src/main/java/com/onekeycall/videotablet/handler/GlobalExceptionHandler.java b/src/main/java/com/onekeycall/videotablet/handler/GlobalExceptionHandler.java
index 61855e7..2572cd2 100644
--- a/src/main/java/com/onekeycall/videotablet/handler/GlobalExceptionHandler.java
+++ b/src/main/java/com/onekeycall/videotablet/handler/GlobalExceptionHandler.java
@@ -2,6 +2,7 @@ package com.onekeycall.videotablet.handler;
import com.onekeycall.videotablet.result.Result;
import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
@@ -9,7 +10,9 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.servlet.resource.NoResourceFoundException;
+import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.Map;
@@ -23,6 +26,14 @@ import java.util.Map;
@ControllerAdvice
public class GlobalExceptionHandler {
+ // 替换为 WebFlux 的异常处理
+// @ExceptionHandler(ResponseStatusException.class)
+// public Mono> handleResponseStatusException(ResponseStatusException ex) {
+// return Mono.just(ResponseEntity
+// .status(ex.getStatusCode())
+// .body(ex.getReason()));
+// }
+
/**
* 使用ExceptionHandler注解声明处理Exception异常
*
@@ -51,12 +62,12 @@ public class GlobalExceptionHandler {
@ResponseBody
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(NoResourceFoundException.class)
- public Result handleNoResourceFoundException(NoResourceFoundException ex) {
+ public ResponseEntity> handleNoResourceFoundException(NoResourceFoundException ex) {
ex.printStackTrace();
// 新版本 Spring(推荐)我没有这个方法
// return ResponseEntity.notFound().body(error);
// 旧版本 Spring(兼容写法)
- return Result.notFound().message("检查网址是否正确");
+ return new ResponseEntity<>(Result.notFound().message("检查网址是否正确"), HttpStatus.BAD_REQUEST);
}
@ResponseBody
diff --git a/src/main/java/com/onekeycall/videotablet/utils/JwtUtil.java b/src/main/java/com/onekeycall/videotablet/utils/JwtUtil.java
index dba9a4a..06c9992 100644
--- a/src/main/java/com/onekeycall/videotablet/utils/JwtUtil.java
+++ b/src/main/java/com/onekeycall/videotablet/utils/JwtUtil.java
@@ -29,11 +29,12 @@ public class JwtUtil {
private Long refreshExpire;
/**
- * @param userId 统一使用user_id
+ * 生成双Token(关联设备指纹)
+ *
+ * @param userId 统一使用user_id
* @param deviceId
* @return
*/
- // 生成双Token(关联设备指纹)
public TokenPair generateTokenPair(String userId, String deviceId) {
String accessToken = Jwts.builder()
.subject(userId)
@@ -64,7 +65,13 @@ public class JwtUtil {
return new TokenPair(accessToken, refreshToken, accessExpire, refreshExpire, deviceId);
}
- // 解析Token并返回Claims
+
+ /**
+ * 解析Token并返回Claims
+ *
+ * @param token
+ * @return
+ */
public Claims parseToken(String token) {
try {
return Jwts.parser()
@@ -77,7 +84,14 @@ public class JwtUtil {
}
}
- // 校验Access Token有效性(签名+过期时间+设备绑定)
+ /**
+ * 校验Access Token有效性(签名+过期时间+设备绑定)
+ *
+ * @param userId
+ * @param accessToken
+ * @param deviceId
+ * @return
+ */
public boolean validateAccessToken(String userId, String accessToken, String deviceId) {
Claims claims = parseToken(accessToken);
@@ -102,7 +116,14 @@ public class JwtUtil {
return true; // 通过所有校验
}
- // 校验Refresh Token有效性(签名+Redis一致性)
+
+ /**
+ * 校验Refresh Token有效性(签名+Redis一致性)
+ *
+ * @param refreshToken
+ * @param username
+ * @return
+ */
public boolean validateRefreshToken(String refreshToken, String username) {
Claims claims = parseToken(refreshToken);
@@ -127,7 +148,14 @@ public class JwtUtil {
return true; // 通过所有校验
}
- // 使用Refresh Token刷新Access Token
+
+ /**
+ * 使用Refresh Token刷新Access Token
+ *
+ * @param refreshToken
+ * @param deviceId
+ * @return
+ */
public TokenPair refreshAccessToken(String refreshToken, String deviceId) {
Claims claims = parseToken(refreshToken);
String userId = claims.getSubject();