主备迁移只webflux
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String, Object> 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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<ResponseEntity<String>> 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
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user