分离注册登录接口

This commit is contained in:
2025-09-08 20:16:29 +08:00
parent a33eeef27e
commit 1b857e1493
8 changed files with 115 additions and 165 deletions

View File

@@ -11,7 +11,6 @@ import org.springframework.security.config.annotation.authentication.configurati
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;

View File

@@ -20,6 +20,8 @@ import java.util.*;
@RestController @RestController
@RequestMapping("/public") @RequestMapping("/public")
public class LoginController { public class LoginController {
Logger logger = LoggerFactory.getLogger(LoginController.class);
private final UserService userService; private final UserService userService;
private final AuthenticationManager authenticationManager; private final AuthenticationManager authenticationManager;
@@ -29,7 +31,6 @@ public class LoginController {
@Autowired @Autowired
private JwtUtil jwtUtil; private JwtUtil jwtUtil;
Logger logger = LoggerFactory.getLogger(LoginController.class);
@Autowired @Autowired
public LoginController(UserService userService, AuthenticationManager authenticationManager) { public LoginController(UserService userService, AuthenticationManager authenticationManager) {
@@ -37,17 +38,6 @@ public class LoginController {
this.authenticationManager = authenticationManager; this.authenticationManager = authenticationManager;
} }
@PostMapping("/register")
public Result registerUser(@RequestHeader("Device-ID") String deviceId,
@RequestParam(value = "user_id") String userId, @RequestParam String password) {
try {
userService.registerUser(userId, password);
return Result.ok().message("User registered successfully");
} catch (RuntimeException e) {
return Result.error().message(e.getMessage());
}
}
@PostMapping("/login") @PostMapping("/login")
public Result login( public Result login(
@RequestHeader("Device-ID") String deviceId, @RequestHeader("Device-ID") String deviceId,
@@ -59,8 +49,8 @@ public class LoginController {
Authentication authentication = authenticationManager.authenticate(authenticationToken); Authentication authentication = authenticationManager.authenticate(authenticationToken);
// 3. 认证成功后生成 JWT // 3. 认证成功后生成 JWT
User userDetails = (User) authentication.getPrincipal(); User user = (User) authentication.getPrincipal();
TokenPair tokenPair = jwtUtil.generateTokenPair(userDetails.getUserId(), deviceId); TokenPair tokenPair = jwtUtil.generateTokenPair(user.getUserId(), deviceId);
// 4. 返回 Token // 4. 返回 Token
return Result.ok().data(Collections.singletonMap("token", tokenPair.toMap())); return Result.ok().data(Collections.singletonMap("token", tokenPair.toMap()));
@@ -100,50 +90,10 @@ public class LoginController {
} }
} }
@PostMapping("/phone_register")
public Result registerByPhone(
@RequestParam String phone, @RequestParam String code,
@RequestParam(value = "verify_key") String verifyKey, @RequestParam(value = "device_id") String deviceId) {
logger.info("registerByPhone: phone={}, code={}, verifyKey={}, deviceId={}", phone, code, verifyKey, deviceId);
// if (TextUtils.isEmpty(verifyKey)) {
// return Result.error().message("verify key is empty", HttpStatus.BAD_REQUEST);
// }
Map<String, Object> map = (Map<String, Object>) redisTemplate.opsForValue().get(phone);
if (map != null) {
String redisVerifyKey = (String) map.get("verifyKey");
if (!Objects.equals(redisVerifyKey, verifyKey)) {
return Result.error().message("verify key is not same");
}
String redisCode = map.get("code").toString();
if (!Objects.equals(redisCode, code)) {
return Result.error().message("code is not same");
}
try {
User user = userService.registerByPhone(phone, code, deviceId, new Date());
logger.info("loginByPhoneCode: user={}", user.toString());
TokenPair tokenPair = jwtUtil.generateTokenPair(user.getUserId(), deviceId);
//返回给app保存access_token用来加入header请求接口refresh_token用来更换access_token
Map<String, Object> tokenMap = new HashMap<>();
tokenMap.put("new_user", user.isNewUser());
tokenMap.put("user_id", user.getUserId());
tokenMap.put("has_password", user.isHasPassword());
tokenMap.put("token", tokenPair.toMap());
redisTemplate.delete(phone);
return Result.ok().data(tokenMap);
} catch (RuntimeException e) {
return Result.error().message(e.getMessage());
}
} else {
// return Result.error().message("verify key is expired");
return Result.error().message("验证码已过期,请重新获取");
}
}
@PostMapping("/phone_code_login") @PostMapping("/phone_code_login")
public Result loginByPhoneCode( public Result loginByPhoneCode(
@RequestParam String phone, @RequestParam String code, @RequestParam String phone, @RequestParam String code,
@RequestParam(value = "verify_key") String verifyKey, @RequestParam(value = "device_id") String deviceId) { @RequestParam(value = "verify_key") String verifyKey, @RequestParam(value = "Device-ID") String deviceId) {
Map<String, Object> map = (Map<String, Object>) redisTemplate.opsForValue().get(phone); Map<String, Object> map = (Map<String, Object>) redisTemplate.opsForValue().get(phone);
if (map != null) { if (map != null) {
String redisVerifyKey = (String) map.get("verifyKey"); String redisVerifyKey = (String) map.get("verifyKey");
@@ -174,10 +124,4 @@ public class LoginController {
} }
} }
// @PostMapping("/device_login")
// public Result loginByDeviceSn(){
//
// }
} }

View File

@@ -0,0 +1,89 @@
package com.onekeycall.videotablet.controller.pub;
import com.onekeycall.videotablet.dto.TokenPair;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@RestController
@RequestMapping("/public")
public class RegisterController {
Logger logger = LoggerFactory.getLogger(RegisterController.class);
private final UserService userService;
private final AuthenticationManager authenticationManager;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private JwtUtil jwtUtil;
public RegisterController(UserService userService, AuthenticationManager authenticationManager) {
this.userService = userService;
this.authenticationManager = authenticationManager;
}
@PostMapping("/register")
public Result registerUser(@RequestHeader("Device-ID") String deviceId,
@RequestParam(value = "user_id") String userId, @RequestParam String password) {
try {
userService.registerUser(userId, password);
return Result.ok().message("User registered successfully");
} catch (RuntimeException e) {
return Result.error().message(e.getMessage());
}
}
@PostMapping("/phone_register")
public Result registerByPhone(
@RequestParam String phone, @RequestParam String code,
@RequestParam(value = "verify_key") String verifyKey, @RequestParam(value = "Device-ID") String deviceId) {
logger.info("registerByPhone: phone={}, code={}, verifyKey={}, deviceId={}", phone, code, verifyKey, deviceId);
// if (TextUtils.isEmpty(verifyKey)) {
// return Result.error().message("verify key is empty", HttpStatus.BAD_REQUEST);
// }
Map<String, Object> map = (Map<String, Object>) redisTemplate.opsForValue().get(phone);
if (map != null) {
String redisVerifyKey = (String) map.get("verifyKey");
if (!Objects.equals(redisVerifyKey, verifyKey)) {
return Result.error().message("verify key is not same");
}
String redisCode = map.get("code").toString();
if (!Objects.equals(redisCode, code)) {
return Result.error().message("code is not same");
}
try {
User user = userService.registerByPhone(phone, code, deviceId, new Date());
logger.info("loginByPhoneCode: user={}", user.toString());
TokenPair tokenPair = jwtUtil.generateTokenPair(user.getUserId(), deviceId);
//返回给app保存access_token用来加入header请求接口refresh_token用来更换access_token
Map<String, Object> tokenMap = new HashMap<>();
tokenMap.put("new_user", user.isNewUser());
tokenMap.put("user_id", user.getUserId());
tokenMap.put("has_password", user.isHasPassword());
tokenMap.put("token", tokenPair.toMap());
redisTemplate.delete(phone);
return Result.ok().data(tokenMap);
} catch (RuntimeException e) {
return Result.error().message(e.getMessage());
}
} else {
// return Result.error().message("verify key is expired");
return Result.error().message("验证码已过期,请重新获取");
}
}
}

View File

@@ -3,6 +3,7 @@ package com.onekeycall.videotablet.entity;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.onekeycall.videotablet.converter.AesAttributeConverter; import com.onekeycall.videotablet.converter.AesAttributeConverter;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
@@ -11,6 +12,7 @@ import java.util.Collections;
import java.util.Date; import java.util.Date;
@Entity @Entity
@Data
@Table(name = "ordinary_users") @Table(name = "ordinary_users")
public class User implements UserDetails { public class User implements UserDetails {
@@ -54,6 +56,12 @@ public class User implements UserDetails {
@Column(name = "avatar") @Column(name = "avatar")
private String avatar; private String avatar;
@Column(name = "gender")
private String gender;
@Column(name = "mobile_system")
private Integer mobileSystem;
@Override @Override
public Collection<? extends GrantedAuthority> getAuthorities() { public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.emptyList(); return Collections.emptyList();
@@ -79,53 +87,12 @@ public class User implements UserDetails {
return true; return true;
} }
public boolean isNewUser() {
return newUser;
}
public void setNewUser(boolean newUser) {
this.newUser = newUser;
}
public boolean isHasPassword() {
return hasPassword;
}
public void setHasPassword(boolean hasPassword) {
this.hasPassword = hasPassword;
}
// Getters and Setters for id, username, password, email
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getUsername() { public String getUsername() {
return userId; return userId;
} }
public void setUsername(String username) { public void setUsername(String userId) {
this.userId = username; this.userId = userId;
} }
public String getPassword() { public String getPassword() {
@@ -136,54 +103,6 @@ public class User implements UserDetails {
this.password = password; this.password = password;
} }
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Date getCreatTime() {
return creatTime;
}
public void setCreatTime(Date creatTime) {
this.creatTime = creatTime;
}
public Date getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(Date lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
@Override @Override
public String toString() { public String toString() {
return new Gson().toJson(this); return new Gson().toJson(this);

View File

@@ -3,9 +3,11 @@ package com.onekeycall.videotablet.filter;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.onekeycall.videotablet.entity.DeviceInfo; import com.onekeycall.videotablet.entity.DeviceInfo;
import com.onekeycall.videotablet.entity.User;
import com.onekeycall.videotablet.gson.GsonUtils; import com.onekeycall.videotablet.gson.GsonUtils;
import com.onekeycall.videotablet.result.Result; import com.onekeycall.videotablet.result.Result;
import com.onekeycall.videotablet.service.DeviceSnService; import com.onekeycall.videotablet.service.DeviceSnService;
import com.onekeycall.videotablet.service.UserService;
import com.onekeycall.videotablet.utils.JwtUtil; import com.onekeycall.videotablet.utils.JwtUtil;
import com.onekeycall.videotablet.utils.TextUtils; import com.onekeycall.videotablet.utils.TextUtils;
import io.jsonwebtoken.lang.Collections; import io.jsonwebtoken.lang.Collections;
@@ -16,11 +18,8 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
@@ -34,7 +33,7 @@ import java.nio.charset.StandardCharsets;
public class JwtAuthenticationFilter extends OncePerRequestFilter { public class JwtAuthenticationFilter extends OncePerRequestFilter {
Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class); Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
private final UserDetailsService userDetailsService; private final UserService userService;
private final JwtUtil jwtUtil; private final JwtUtil jwtUtil;
@@ -81,17 +80,17 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
// 如果获取到用户名且当前上下文没有认证信息 // 如果获取到用户名且当前上下文没有认证信息
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); User user = this.userService.loadUserByUsername(username);
// 新增权限检查日志 // 新增权限检查日志
logger.debug("Loaded user authorities: " + userDetails.getAuthorities()); logger.debug("Loaded user authorities: " + user.getAuthorities());
// 验证Token // 验证Token
if (jwtUtil.validateToken(jwt, userDetails)) { if (jwtUtil.validateToken(jwt, user)) {
// 创建认证令牌 // 创建认证令牌
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken( new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities()); user, null, user.getAuthorities());
usernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(wrappedRequest)); .setDetails(new WebAuthenticationDetailsSource().buildDetails(wrappedRequest));
@@ -108,7 +107,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
} else if (uripath.startsWith("/sn")) { } else if (uripath.startsWith("/sn")) {
// 设备绑定相关鉴权 // 设备绑定相关鉴权
String deviceToken = wrappedRequest.getHeader("Device-Token"); String deviceToken = wrappedRequest.getHeader("Device-Token");
String deviceId = wrappedRequest.getHeader("Device-Id"); String deviceId = wrappedRequest.getHeader("Device-ID");
String deviceSig = wrappedRequest.getHeader("Device-Sig"); String deviceSig = wrappedRequest.getHeader("Device-Sig");
String sn = null; String sn = null;

View File

@@ -30,7 +30,7 @@ public class SignalingHandler extends TextWebSocketHandler {
@Override @Override
public void afterConnectionEstablished(WebSocketSession session) { public void afterConnectionEstablished(WebSocketSession session) {
String deviceId = session.getHandshakeHeaders().getFirst("device-id"); String deviceId = session.getHandshakeHeaders().getFirst("Device-ID");
sessions.put(deviceId, session); // 保存会话 sessions.put(deviceId, session); // 保存会话
} }
} }

View File

@@ -8,7 +8,6 @@ import com.onekeycall.videotablet.utils.SecureIdGenerator;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
@@ -92,7 +91,7 @@ public class UserService implements UserDetailsService {
} }
@Override @Override
public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundException { public User loadUserByUsername(String userId) throws UsernameNotFoundException {
return userRepository.findByUserId(userId) return userRepository.findByUserId(userId)
.orElseThrow(() -> new UsernameNotFoundException("User not found with userId: " + userId)); .orElseThrow(() -> new UsernameNotFoundException("User not found with userId: " + userId));
} }

View File

@@ -1,6 +1,7 @@
package com.onekeycall.videotablet.utils; package com.onekeycall.videotablet.utils;
import com.onekeycall.videotablet.dto.TokenPair; import com.onekeycall.videotablet.dto.TokenPair;
import com.onekeycall.videotablet.entity.User;
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException; import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts; import io.jsonwebtoken.Jwts;