接口修正、成就修正、学习记录修正

This commit is contained in:
2025-11-03 17:12:40 +08:00
parent 35aee59178
commit b95fff224b
28 changed files with 730 additions and 302 deletions

View File

@@ -435,14 +435,13 @@ public class AuthController {
return result;
}
// 3. 密码加密
String encryptedPassword = passwordEncoder.encode(password);
user.setPassword(encryptedPassword);
// 3. 设置密码明文Service层会加密
user.setPassword(password);
// 4. 设置用户状态为正常
user.setStatus(0);
// 5. 调用UserService注册用户
// 5. 调用UserService注册用户Service层会加密密码
ResultDomain<TbSysUser> registerResult = userService.registerUser(user);
if (!registerResult.isSuccess()) {

View File

@@ -7,9 +7,11 @@ import org.xyzh.common.dto.user.TbSysUser;
import org.xyzh.common.dto.dept.TbSysDeptRole;
import org.xyzh.common.dto.permission.TbSysPermission;
import org.xyzh.common.core.enums.UserStatus;
import org.xyzh.common.vo.UserDeptRoleVO;
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -36,6 +38,29 @@ public class UserPrincipal implements UserDetails {
return new UserPrincipal(user, roles, permissions);
}
/**
* @description 从LoginDomain创建UserPrincipal用于从Redis缓存恢复认证信息
* @param user 用户信息
* @param userDeptRoles 用户部门角色列表来自LoginDomain
* @param permissions 权限列表
* @return UserPrincipal 用户主体
* @author yslg
* @since 2025-11-03
*/
public static UserPrincipal createFromLoginDomain(TbSysUser user, List<UserDeptRoleVO> userDeptRoles, List<TbSysPermission> permissions) {
// 将UserDeptRoleVO转换为TbSysDeptRole简化处理实际使用时UserDeptRoleVO已包含所需信息
List<TbSysDeptRole> roles = new ArrayList<>();
if (userDeptRoles != null) {
for (UserDeptRoleVO vo : userDeptRoles) {
TbSysDeptRole role = new TbSysDeptRole();
role.setRoleID(vo.getRoleID());
role.setDeptID(vo.getDeptID());
roles.add(role);
}
}
return new UserPrincipal(user, roles, permissions != null ? permissions : new ArrayList<>());
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// 角色权限

View File

@@ -12,12 +12,16 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.xyzh.auth.service.UserDetailsServiceImpl;
import org.xyzh.auth.util.JwtTokenUtil;
import org.xyzh.auth.config.AuthProperties;
import org.xyzh.common.core.domain.LoginDomain;
import org.xyzh.common.redis.service.RedisService;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @description JwtAuthenticationFilter.java文件描述 JWT认证过滤器
* @filename JwtAuthenticationFilter.java
@@ -28,14 +32,18 @@ import java.io.IOException;
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private static final String REDIS_LOGIN_PREFIX = "login:token:";
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private UserDetailsServiceImpl userDetailsService;
private AuthProperties authProperties;
@Autowired
private AuthProperties authProperties;
private RedisService redisService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
@@ -56,17 +64,38 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
String userId = jwtTokenUtil.getUserIdFromToken(token);
if (userId != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUserId(userId);
// 验证token有效性
if (!jwtTokenUtil.validateToken(token, userId)) {
logger.warn("Token验证失败userId: {}", userId);
filterChain.doFilter(request, response);
return;
}
if (jwtTokenUtil.validateToken(token, userId)) {
// 【优化】从Redis缓存中获取LoginDomain避免每次都查数据库
String redisKey = REDIS_LOGIN_PREFIX + userId;
LoginDomain loginDomain = (LoginDomain) redisService.get(redisKey);
if (loginDomain != null && loginDomain.getUser() != null) {
// 【优化】直接使用缓存中的用户信息构建UserDetails不查数据库
// 使用UserPrincipal从LoginDomain创建UserDetails
UserDetails userDetails = org.xyzh.auth.domain.UserPrincipal.createFromLoginDomain(
loginDomain.getUser(),
loginDomain.getRoles(),
loginDomain.getPermissions()
);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
logger.debug("用户认证成功从缓存userId: {}", userId);
} else {
logger.warn("Redis缓存中未找到用户登录信息userId: {}, 可能已过期或未登录", userId);
}
}
} catch (Exception e) {
logger.error("JWT token validation failed: " + e.getMessage());
logger.error("JWT token validation failed: " + e.getMessage(), e);
}
}

View File

@@ -1,103 +0,0 @@
package org.xyzh.auth.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.xyzh.auth.domain.UserPrincipal;
import org.xyzh.common.dto.user.TbSysUser;
import org.xyzh.common.dto.dept.TbSysDeptRole;
import org.xyzh.common.dto.permission.TbSysPermission;
import org.xyzh.api.system.user.UserService;
import org.xyzh.api.system.role.RoleService;
import org.xyzh.api.system.permission.PermissionService;
import java.util.List;
import java.util.ArrayList;
/**
* @description UserDetailsServiceImpl.java文件描述 用户详情服务实现
* @filename UserDetailsServiceImpl.java
* @author yslg
* @copyright xyzh
* @since 2025-09-28
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
private static final Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
@Autowired
private UserService userService;
@Autowired(required = false)
private RoleService roleService;
@Autowired(required = false)
private PermissionService permissionService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
TbSysUser filter = new TbSysUser();
filter.setUsername(username);
List<TbSysUser> users = userService.getUserByFilter(filter).getDataList();
if(users.isEmpty()) {
throw new UsernameNotFoundException("用户不存在: " + username);
}
TbSysUser user = users.get(0);
if (user == null) {
throw new UsernameNotFoundException("用户不存在: " + username);
}
return loadUserByUserId(user.getID());
}
/**
* @description 根据用户ID加载用户详情
* @param userId 用户ID
* @return UserDetails 用户详情
* @author yslg
* @since 2025-09-28
*/
public UserDetails loadUserByUserId(String userId) {
TbSysUser filter = new TbSysUser();
filter.setID(userId);
List<TbSysUser> users = userService.getUserByFilter(filter).getDataList();
if(users.isEmpty()) {
throw new UsernameNotFoundException("用户不存在: " + userId);
}
TbSysUser user = users.get(0);
if (user == null) {
throw new UsernameNotFoundException("用户不存在: " + userId);
}
// 获取用户角色(如果角色服务可用)
List<TbSysDeptRole> roles = new ArrayList<>();
if (roleService != null) {
try {
// TODO: 需要在RoleService中实现findRolesByUserId方法
// roles = roleService.findRolesByUserId(userId);
} catch (Exception e) {
logger.warn("无法获取用户角色: " + e.getMessage());
}
}
// 获取用户权限(如果权限服务可用)
List<TbSysPermission> permissions = new ArrayList<>();
if (permissionService != null) {
try {
// TODO: 需要在PermissionService中实现findPermissionsByUserId方法
// permissions = permissionService.findPermissionsByUserId(userId);
} catch (Exception e) {
logger.warn("无法获取用户权限: " + e.getMessage());
}
}
return UserPrincipal.create(user, roles, permissions);
}
}

View File

@@ -65,7 +65,8 @@ public class PasswordLoginStrategy implements LoginStrategy {
}else{
filter.setUsername(loginParam.getUsername());
}
filter.setPassword(passwordEncoder.encode(loginParam.getPassword()));
// 【优化】删除无用的密码编码SQL查询不使用password字段
// 密码验证在 verifyCredential() 方法中进行
TbSysUser user = userService.getLoginUser(filter).getData();
if(user == null) {
return null;
@@ -75,7 +76,7 @@ public class PasswordLoginStrategy implements LoginStrategy {
@Override
public boolean verifyCredential(String inputCredential, String storedCredential) {
logger.info(passwordEncoder.encode(inputCredential));
// 使用BCrypt的matches方法验证密码内部会自动处理salt
return passwordEncoder.matches(inputCredential, storedCredential);
}
}