refactor: 获取用户认证凭证优化

This commit is contained in:
Ray.Hao
2025-03-31 08:18:46 +08:00
parent 594eb2befb
commit 60cfa78a52
11 changed files with 61 additions and 63 deletions

View File

@@ -65,12 +65,12 @@ public class SecurityConfig {
return http return http
.authorizeHttpRequests(requestMatcherRegistry -> { .authorizeHttpRequests(requestMatcherRegistry -> {
// 忽略认证的 URI 地址 // 配置无需登录即可访问的公开接口
String[] ignoreUrls = securityProperties.getIgnoreUrls(); String[] ignoreUrls = securityProperties.getIgnoreUrls();
if (ArrayUtil.isNotEmpty(ignoreUrls)) { if (ArrayUtil.isNotEmpty(ignoreUrls)) {
requestMatcherRegistry.requestMatchers(ignoreUrls).permitAll(); requestMatcherRegistry.requestMatchers(ignoreUrls).permitAll();
} }
// 其他请求都需要认证 // 其他所有请求需登录后访问
requestMatcherRegistry.anyRequest().authenticated(); requestMatcherRegistry.anyRequest().authenticated();
} }
) )

View File

@@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil;
import com.youlai.boot.common.constant.RedisConstants; import com.youlai.boot.common.constant.RedisConstants;
import com.youlai.boot.core.security.exception.CaptchaValidationException; import com.youlai.boot.core.security.exception.CaptchaValidationException;
import com.youlai.boot.core.security.model.SysUserDetails; import com.youlai.boot.core.security.model.SysUserDetails;
import com.youlai.boot.system.model.dto.UserAuthInfo; import com.youlai.boot.core.security.model.AuthCredentials;
import com.youlai.boot.system.service.UserService; import com.youlai.boot.system.service.UserService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@@ -49,14 +49,14 @@ public class SmsAuthenticationProvider implements AuthenticationProvider {
String inputVerifyCode = (String) authentication.getCredentials(); String inputVerifyCode = (String) authentication.getCredentials();
// 根据手机号获取用户信息 // 根据手机号获取用户信息
UserAuthInfo userAuthInfo = userService.getUserAuthInfoByMobile(mobile); AuthCredentials authCredentials = userService.getAuthCredentialsByMobile(mobile);
if (userAuthInfo == null) { if (authCredentials == null) {
throw new UsernameNotFoundException("用户不存在"); throw new UsernameNotFoundException("用户不存在");
} }
// 检查用户状态是否有效 // 检查用户状态是否有效
if (ObjectUtil.notEqual(userAuthInfo.getStatus(), 1)) { if (ObjectUtil.notEqual(authCredentials.getStatus(), 1)) {
throw new DisabledException("用户已被禁用"); throw new DisabledException("用户已被禁用");
} }
@@ -72,7 +72,7 @@ public class SmsAuthenticationProvider implements AuthenticationProvider {
} }
// 构建认证后的用户详情信息 // 构建认证后的用户详情信息
SysUserDetails userDetails = new SysUserDetails(userAuthInfo); SysUserDetails userDetails = new SysUserDetails(authCredentials);
// 创建已认证的 SmsAuthenticationToken // 创建已认证的 SmsAuthenticationToken
return SmsAuthenticationToken.authenticated( return SmsAuthenticationToken.authenticated(

View File

@@ -5,7 +5,7 @@ import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.youlai.boot.core.security.model.SysUserDetails; import com.youlai.boot.core.security.model.SysUserDetails;
import com.youlai.boot.system.model.dto.UserAuthInfo; import com.youlai.boot.core.security.model.AuthCredentials;
import com.youlai.boot.system.service.UserService; import com.youlai.boot.system.service.UserService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxErrorException;
@@ -63,27 +63,27 @@ public class WechatAuthenticationProvider implements AuthenticationProvider {
} }
// 根据微信 OpenID 查询用户信息 // 根据微信 OpenID 查询用户信息
UserAuthInfo userAuthInfo = userService.getUserAuthInfoByOpenId(openId); AuthCredentials authCredentials = userService.getAuthCredentialsByOpenId(openId);
if (userAuthInfo == null) { if (authCredentials == null) {
// TODO: 用户不存在则注册,这里需要获取用户手机号并与现有用户绑定 // TODO: 用户不存在则注册,这里需要获取用户手机号并与现有用户绑定
userService.registerOrBindWechatUser(openId); userService.registerOrBindWechatUser(openId);
// 再次查询用户信息,确保用户注册成功 // 再次查询用户信息,确保用户注册成功
userAuthInfo = userService.getUserAuthInfoByOpenId(openId); authCredentials = userService.getAuthCredentialsByOpenId(openId);
if (userAuthInfo == null) { if (authCredentials == null) {
throw new UsernameNotFoundException("用户注册失败,请稍后重试"); throw new UsernameNotFoundException("用户注册失败,请稍后重试");
} }
} }
// 检查用户状态是否有效 // 检查用户状态是否有效
if (ObjectUtil.notEqual(userAuthInfo.getStatus(), 1)) { if (ObjectUtil.notEqual(authCredentials.getStatus(), 1)) {
throw new DisabledException("用户已被禁用"); throw new DisabledException("用户已被禁用");
} }
// 这里因为已经根据 code 从微信小程序获取到 openid 不需要再经过系统认证,所以直接生成 // 这里因为已经根据 code 从微信小程序获取到 openid 不需要再经过系统认证,所以直接生成
// 构建认证后的用户详情信息 // 构建认证后的用户详情信息
SysUserDetails userDetails = new SysUserDetails(userAuthInfo); SysUserDetails userDetails = new SysUserDetails(authCredentials);
// 创建已认证的 WeChatAuthenticationToken // 创建已认证的 WeChatAuthenticationToken
return WechatAuthenticationToken.authenticated( return WechatAuthenticationToken.authenticated(

View File

@@ -56,7 +56,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
return; return;
} }
// 将令牌解析为Spring Security认证对象 // 将令牌解析为 Spring Security 上下文认证对象
Authentication authentication = tokenManager.parseToken(rawToken); Authentication authentication = tokenManager.parseToken(rawToken);
SecurityContextHolder.getContext().setAuthentication(authentication); SecurityContextHolder.getContext().setAuthentication(authentication);
} }

View File

@@ -1,17 +1,16 @@
package com.youlai.boot.system.model.dto; package com.youlai.boot.core.security.model;
import lombok.Data; import lombok.Data;
import java.util.Set; import java.util.Set;
/** /**
* 用户认证信息 * 用户认证凭证信息
* *
* @author Ray.Hao * @author Ray.Hao
* @since 2022/10/22 * @since 2022/10/22
*/ */
@Data @Data
public class UserAuthInfo { public class AuthCredentials {
/** /**
* 用户ID * 用户ID

View File

@@ -3,7 +3,6 @@ package com.youlai.boot.core.security.model;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.youlai.boot.common.constant.SecurityConstants; import com.youlai.boot.common.constant.SecurityConstants;
import com.youlai.boot.system.model.dto.UserAuthInfo;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
@@ -65,9 +64,9 @@ public class SysUserDetails implements UserDetails {
/** /**
* 构造函数:根据用户认证信息初始化用户详情对象 * 构造函数:根据用户认证信息初始化用户详情对象
* *
* @param user 用户认证信息对象 {@link UserAuthInfo} * @param user 用户认证信息对象 {@link AuthCredentials}
*/ */
public SysUserDetails(UserAuthInfo user) { public SysUserDetails(AuthCredentials user) {
this.userId = user.getUserId(); this.userId = user.getUserId();
this.username = user.getUsername(); this.username = user.getUsername();
this.password = user.getPassword(); this.password = user.getPassword();

View File

@@ -1,7 +1,7 @@
package com.youlai.boot.core.security.service; package com.youlai.boot.core.security.service;
import com.youlai.boot.core.security.model.SysUserDetails; import com.youlai.boot.core.security.model.SysUserDetails;
import com.youlai.boot.system.model.dto.UserAuthInfo; import com.youlai.boot.core.security.model.AuthCredentials;
import com.youlai.boot.system.service.UserService; import com.youlai.boot.system.service.UserService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -33,11 +33,11 @@ public class SysUserDetailsService implements UserDetailsService {
@Override @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try { try {
UserAuthInfo userAuthInfo = userService.getUserAuthInfo(username); AuthCredentials authCredentials = userService.getAuthCredentialsByUsername(username);
if (userAuthInfo == null) { if (authCredentials == null) {
throw new UsernameNotFoundException(username); throw new UsernameNotFoundException(username);
} }
return new SysUserDetails(userAuthInfo); return new SysUserDetails(authCredentials);
} catch (Exception e) { } catch (Exception e) {
// 记录异常日志 // 记录异常日志
log.error("认证异常:{}", e.getMessage()); log.error("认证异常:{}", e.getMessage());

View File

@@ -7,7 +7,7 @@ import com.youlai.boot.system.model.entity.User;
import com.youlai.boot.system.model.query.UserPageQuery; import com.youlai.boot.system.model.query.UserPageQuery;
import com.youlai.boot.system.model.form.UserForm; import com.youlai.boot.system.model.form.UserForm;
import com.youlai.boot.common.annotation.DataPermission; import com.youlai.boot.common.annotation.DataPermission;
import com.youlai.boot.system.model.dto.UserAuthInfo; import com.youlai.boot.core.security.model.AuthCredentials;
import com.youlai.boot.system.model.dto.UserExportDTO; import com.youlai.boot.system.model.dto.UserExportDTO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@@ -46,7 +46,7 @@ public interface UserMapper extends BaseMapper<User> {
* @param username 用户名 * @param username 用户名
* @return 认证信息 * @return 认证信息
*/ */
UserAuthInfo getUserAuthInfo(String username); AuthCredentials getAuthCredentialsByUsername(String username);
/** /**
* 根据微信openid获取用户认证信息 * 根据微信openid获取用户认证信息
@@ -54,7 +54,7 @@ public interface UserMapper extends BaseMapper<User> {
* @param openid 微信openid * @param openid 微信openid
* @return 认证信息 * @return 认证信息
*/ */
UserAuthInfo getUserAuthInfoByOpenId(String openid); AuthCredentials getAuthCredentialsByOpenId(String openid);
/** /**
* 根据手机号获取用户认证信息 * 根据手机号获取用户认证信息
@@ -62,7 +62,7 @@ public interface UserMapper extends BaseMapper<User> {
* @param mobile 手机号 * @param mobile 手机号
* @return 认证信息 * @return 认证信息
*/ */
UserAuthInfo getUserAuthInfoByMobile(String mobile); AuthCredentials getAuthCredentialsByMobile(String mobile);
/** /**
* 获取导出用户列表 * 获取导出用户列表

View File

@@ -3,7 +3,7 @@ package com.youlai.boot.system.service;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.youlai.boot.common.model.Option; import com.youlai.boot.common.model.Option;
import com.youlai.boot.system.model.dto.UserAuthInfo; import com.youlai.boot.core.security.model.AuthCredentials;
import com.youlai.boot.system.model.dto.UserExportDTO; import com.youlai.boot.system.model.dto.UserExportDTO;
import com.youlai.boot.system.model.entity.User; import com.youlai.boot.system.model.entity.User;
import com.youlai.boot.system.model.query.UserPageQuery; import com.youlai.boot.system.model.query.UserPageQuery;
@@ -69,10 +69,10 @@ public interface UserService extends IService<User> {
* 根据用户名获取认证信息 * 根据用户名获取认证信息
* *
* @param username 用户名 * @param username 用户名
* @return {@link UserAuthInfo} * @return {@link AuthCredentials}
*/ */
UserAuthInfo getUserAuthInfo(String username); AuthCredentials getAuthCredentialsByUsername(String username);
/** /**
@@ -166,10 +166,10 @@ public interface UserService extends IService<User> {
* 根据 openid 获取用户认证信息 * 根据 openid 获取用户认证信息
* *
* @param username 用户名 * @param username 用户名
* @return {@link UserAuthInfo} * @return {@link AuthCredentials}
*/ */
UserAuthInfo getUserAuthInfoByOpenId(String username); AuthCredentials getAuthCredentialsByOpenId(String username);
/** /**
* 根据微信 OpenID 注册或绑定用户 * 根据微信 OpenID 注册或绑定用户
@@ -182,9 +182,9 @@ public interface UserService extends IService<User> {
* 根据手机号获取用户认证信息 * 根据手机号获取用户认证信息
* *
* @param mobile 手机号 * @param mobile 手机号
* @return {@link UserAuthInfo} * @return {@link AuthCredentials}
*/ */
UserAuthInfo getUserAuthInfoByMobile(String mobile); AuthCredentials getAuthCredentialsByMobile(String mobile);
} }

View File

@@ -22,7 +22,7 @@ import com.youlai.boot.system.converter.UserConverter;
import com.youlai.boot.system.enums.DictCodeEnum; import com.youlai.boot.system.enums.DictCodeEnum;
import com.youlai.boot.system.mapper.UserMapper; import com.youlai.boot.system.mapper.UserMapper;
import com.youlai.boot.system.model.bo.UserBO; import com.youlai.boot.system.model.bo.UserBO;
import com.youlai.boot.system.model.dto.UserAuthInfo; import com.youlai.boot.core.security.model.AuthCredentials;
import com.youlai.boot.system.model.dto.UserExportDTO; import com.youlai.boot.system.model.dto.UserExportDTO;
import com.youlai.boot.system.model.entity.DictItem; import com.youlai.boot.system.model.entity.DictItem;
import com.youlai.boot.system.model.entity.User; import com.youlai.boot.system.model.entity.User;
@@ -192,54 +192,54 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
* 根据用户名获取认证信息 * 根据用户名获取认证信息
* *
* @param username 用户名 * @param username 用户名
* @return 用户认证信息 {@link UserAuthInfo} * @return 用户认证信息 {@link AuthCredentials}
*/ */
@Override @Override
public UserAuthInfo getUserAuthInfo(String username) { public AuthCredentials getAuthCredentialsByUsername(String username) {
UserAuthInfo userAuthInfo = this.baseMapper.getUserAuthInfo(username); AuthCredentials authCredentials = this.baseMapper.getAuthCredentialsByUsername(username);
if (userAuthInfo != null) { if (authCredentials != null) {
Set<String> roles = userAuthInfo.getRoles(); Set<String> roles = authCredentials.getRoles();
// 获取最大范围的数据权限 // 获取最大范围的数据权限
Integer dataScope = roleService.getMaximumDataScope(roles); Integer dataScope = roleService.getMaximumDataScope(roles);
userAuthInfo.setDataScope(dataScope); authCredentials.setDataScope(dataScope);
} }
return userAuthInfo; return authCredentials;
} }
/** /**
* 根据 openid 获取用户认证信息 * 根据 openid 获取用户认证信息
* *
* @param openid 微信 * @param openid 微信
* @return {@link UserAuthInfo} * @return {@link AuthCredentials}
*/ */
@Override @Override
public UserAuthInfo getUserAuthInfoByOpenId(String openid) { public AuthCredentials getAuthCredentialsByOpenId(String openid) {
UserAuthInfo userAuthInfo = this.baseMapper.getUserAuthInfoByOpenId(openid); AuthCredentials authCredentials = this.baseMapper.getAuthCredentialsByOpenId(openid);
if (userAuthInfo != null) { if (authCredentials != null) {
Set<String> roles = userAuthInfo.getRoles(); Set<String> roles = authCredentials.getRoles();
// 获取最大范围的数据权限 // 获取最大范围的数据权限
Integer dataScope = roleService.getMaximumDataScope(roles); Integer dataScope = roleService.getMaximumDataScope(roles);
userAuthInfo.setDataScope(dataScope); authCredentials.setDataScope(dataScope);
} }
return userAuthInfo; return authCredentials;
} }
/** /**
* 根据手机号获取用户认证信息 * 根据手机号获取用户认证信息
* *
* @param mobile 手机号 * @param mobile 手机号
* @return {@link UserAuthInfo} * @return {@link AuthCredentials}
*/ */
@Override @Override
public UserAuthInfo getUserAuthInfoByMobile(String mobile) { public AuthCredentials getAuthCredentialsByMobile(String mobile) {
UserAuthInfo userAuthInfo = this.baseMapper.getUserAuthInfoByMobile(mobile); AuthCredentials authCredentials = this.baseMapper.getAuthCredentialsByMobile(mobile);
if (userAuthInfo != null) { if (authCredentials != null) {
Set<String> roles = userAuthInfo.getRoles(); Set<String> roles = authCredentials.getRoles();
// 获取最大范围的数据权限 // 获取最大范围的数据权限
Integer dataScope = roleService.getMaximumDataScope(roles); Integer dataScope = roleService.getMaximumDataScope(roles);
userAuthInfo.setDataScope(dataScope); authCredentials.setDataScope(dataScope);
} }
return userAuthInfo; return authCredentials;
} }

View File

@@ -119,7 +119,7 @@
</select> </select>
<!-- 用户认证信息映射 --> <!-- 用户认证信息映射 -->
<resultMap id="UserAuthMap" type="com.youlai.boot.system.model.dto.UserAuthInfo"> <resultMap id="AuthCredentialsMap" type="com.youlai.boot.core.security.model.AuthCredentials">
<id property="userId" column="userId" jdbcType="BIGINT"/> <id property="userId" column="userId" jdbcType="BIGINT"/>
<result property="username" column="username" jdbcType="VARCHAR"/> <result property="username" column="username" jdbcType="VARCHAR"/>
<result property="password" column="password" jdbcType="VARCHAR"/> <result property="password" column="password" jdbcType="VARCHAR"/>
@@ -131,7 +131,7 @@
</resultMap> </resultMap>
<!-- 根据用户名获取用户的认证信息 --> <!-- 根据用户名获取用户的认证信息 -->
<select id="getUserAuthInfo" resultMap="UserAuthMap"> <select id="getAuthCredentialsByUsername" resultMap="AuthCredentialsMap">
SELECT SELECT
t1.id userId, t1.id userId,
t1.username, t1.username,
@@ -149,7 +149,7 @@
</select> </select>
<!-- 根据微信openid获取用户的认证信息 --> <!-- 根据微信openid获取用户的认证信息 -->
<select id="getUserAuthInfoByOpenId" resultMap="UserAuthMap"> <select id="getAuthCredentialsByOpenId" resultMap="AuthCredentialsMap">
SELECT SELECT
t1.id userId, t1.id userId,
t1.username, t1.username,
@@ -167,7 +167,7 @@
</select> </select>
<!-- 根据手机号获取用户的认证信息 --> <!-- 根据手机号获取用户的认证信息 -->
<select id="getUserAuthInfoByMobile" resultMap="UserAuthMap"> <select id="getAuthCredentialsByMobile" resultMap="AuthCredentialsMap">
SELECT SELECT
t1.id userId, t1.id userId,
t1.username, t1.username,