diff --git a/src/main/java/com/youlai/boot/common/constant/SecurityConstants.java b/src/main/java/com/youlai/boot/common/constant/SecurityConstants.java index 5115cce4..a85b1dcb 100644 --- a/src/main/java/com/youlai/boot/common/constant/SecurityConstants.java +++ b/src/main/java/com/youlai/boot/common/constant/SecurityConstants.java @@ -39,4 +39,9 @@ public interface SecurityConstants { * 微信登录路径 */ String WECHAT_LOGIN_PATH = "/api/v1/auth/wechat-login"; + + /** + * 角色前缀 Spring Security 的 authorities 角色前缀,用于区分角色和权限 + */ + String ROLE_PREFIX = "ROLE_"; } diff --git a/src/main/java/com/youlai/boot/core/security/model/SysUserDetails.java b/src/main/java/com/youlai/boot/core/security/model/SysUserDetails.java index 633dbb0d..6005214f 100644 --- a/src/main/java/com/youlai/boot/core/security/model/SysUserDetails.java +++ b/src/main/java/com/youlai/boot/core/security/model/SysUserDetails.java @@ -2,9 +2,9 @@ package com.youlai.boot.core.security.model; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; +import com.youlai.boot.common.constant.SecurityConstants; import com.youlai.boot.system.model.dto.UserAuthInfo; import lombok.Data; -import lombok.Getter; import lombok.NoArgsConstructor; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -12,51 +12,76 @@ import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; import java.util.Collections; -import java.util.Set; import java.util.stream.Collectors; /** - * Spring Security 用户对象 + * Spring Security 用户认证对象 + *

+ * 封装了用户的基本信息和权限信息,供 Spring Security 进行用户认证与授权。 + * 实现了 {@link UserDetails} 接口,提供用户的核心信息。 * - * @author haoxr - * @since 3.0.0 + * @author Ray.Hao + * @version 3.0.0 */ @Data @NoArgsConstructor public class SysUserDetails implements UserDetails { - @Getter + /** + * 用户ID + */ private Long userId; + /** + * 用户名 + */ private String username; + /** + * 密码 + */ private String password; + /** + * 账号是否启用(true:启用,false:禁用) + */ private Boolean enabled; - private Collection authorities; - + /** + * 部门ID + */ private Long deptId; + /** + * 数据权限范围 + */ private Integer dataScope; + /** + * 用户角色权限集合 + */ + private Collection authorities; + + /** + * 构造函数:根据用户认证信息初始化用户详情对象 + * + * @param user 用户认证信息对象 {@link UserAuthInfo} + */ public SysUserDetails(UserAuthInfo user) { this.userId = user.getUserId(); - Set roles = user.getRoles(); - Set authorities; - if (CollectionUtil.isNotEmpty(roles)) { - authorities = roles.stream() - .map(role -> new SimpleGrantedAuthority("ROLE_" + role)) // 标识角色 - .collect(Collectors.toSet()); - } else { - authorities = Collections.emptySet(); - } - this.authorities = authorities; this.username = user.getUsername(); this.password = user.getPassword(); this.enabled = ObjectUtil.equal(user.getStatus(), 1); this.deptId = user.getDeptId(); this.dataScope = user.getDataScope(); + + // 初始化角色权限集合 + this.authorities = CollectionUtil.isNotEmpty(user.getRoles()) + ? user.getRoles().stream() + // 角色名加上前缀 "ROLE_",用于区分角色 (ROLE_ADMIN) 和权限 (user:add) + .map(role -> new SimpleGrantedAuthority(SecurityConstants.ROLE_PREFIX + role)) + .collect(Collectors.toSet()) + : Collections.emptySet(); } diff --git a/src/main/java/com/youlai/boot/core/security/util/SecurityUtils.java b/src/main/java/com/youlai/boot/core/security/util/SecurityUtils.java index 4344ea49..12e41e18 100644 --- a/src/main/java/com/youlai/boot/core/security/util/SecurityUtils.java +++ b/src/main/java/com/youlai/boot/core/security/util/SecurityUtils.java @@ -2,6 +2,7 @@ package com.youlai.boot.core.security.util; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; +import com.youlai.boot.common.constant.SecurityConstants; import com.youlai.boot.common.constant.SystemConstants; import com.youlai.boot.core.security.model.SysUserDetails; import jakarta.servlet.http.HttpServletRequest; @@ -83,21 +84,21 @@ public class SecurityUtils { /** - * 获取用户角色集合 + * 获取角色集合 * * @return 角色集合 */ public static Set getRoles() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication != null) { - Collection authorities = authentication.getAuthorities(); - if (CollectionUtil.isNotEmpty(authorities)) { - return authorities.stream().filter(item -> item.getAuthority().startsWith("ROLE_")) - .map(item -> StrUtil.removePrefix(item.getAuthority(), "ROLE_")) - .collect(Collectors.toSet()); - } - } - return Collections.EMPTY_SET; + return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()) + .map(Authentication::getAuthorities) + .filter(CollectionUtil::isNotEmpty) + .stream() + .flatMap(Collection::stream) + .map(GrantedAuthority::getAuthority) + // 筛选角色,authorities 中的角色都是以 ROLE_ 开头 + .filter(authority -> authority.startsWith(SecurityConstants.ROLE_PREFIX)) + .map(authority -> StrUtil.removePrefix(authority, SecurityConstants.ROLE_PREFIX)) + .collect(Collectors.toSet()); } /**