当前位置: 首页 > news >正文

项目集成Spring Security授权部分

一、需求分析

  • 业务背景
    当前项目采用前后端分离架构,后端需要对接口访问进行严格控制,防止未授权访问。鉴于系统需要支持高并发与分布式部署,采用无状态认证方式显得尤为重要。

  • 核心需求

    • 无状态认证:使用 JWT 作为令牌,前后端分离项目不依赖 session,保障系统的横向扩展能力。
    • 动态权限校验:每个用户的可访问接口列表存储在 Redis 缓存中,通过令牌解析得到用户信息后,再根据缓存中的数据判断是否具备访问权限。
    • 白名单与忽略路径:配置公开接口与忽略路径,允许无需认证的请求(例如登录接口、静态资源等)直接放行。

设计方案

  1. 安全过滤链

    • 使用 Spring Security 提供的 SecurityFilterChain 进行整体安全配置。
    • 从配置文件中读取忽略路径列表,利用 antMatchers 放行这些请求。
    • 对其他请求,委托自定义的 JwtTokenAuthorizationManager 进行权限校验。
  2. JWT 授权管理

    • 通过请求头获取 JWT 令牌,利用工具类解析出 JWT 中包含的用户信息(例如当前用户对象)。
    • 从 Redis 缓存中获取该用户拥有访问权限的 URL 列表,并使用 AntPathMatcher 进行路径匹配,判断当前请求是否在允许列表中。
  3. 其他安全策略

    • 禁用 session 管理(设置为无状态)。
    • 关闭 CSRF 保护(前后端分离场景下通常不需要)。
    • 配置密码加密器(使用 BCrypt 加密)。

二、代码解读

2.1 SecurityConfig 配置类

@Configuration
public class SecurityConfig {@Autowiredprivate JwtTokenAuthorizationManager jwtTokenAuthorizationManager;@Autowiredprivate SecurityConfigProperties securityConfigProperties;@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {// 获取忽略列表,从配置文件加载 ignoreUrl 列表List<String> ignoreUrl = securityConfigProperties.getIgnoreUrl();// 配置放行忽略路径(如登录、注册或其他公共接口)http.authorizeHttpRequests().antMatchers(ignoreUrl.toArray(new String[ignoreUrl.size()])).permitAll()// 其他请求交由自定义 JwtTokenAuthorizationManager 校验权限.anyRequest().access(jwtTokenAuthorizationManager);// 设置无状态会话管理,关闭 session(适用于 RESTful 接口)http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);// 关闭缓存,确保安全头信息不被浏览器缓存http.headers().cacheControl().disable();// 关闭 CSRF(前后端分离项目一般不需要 CSRF 防护)http.csrf().disable();return http.build();}/*** 创建认证管理器 Bean*/@Beanpublic AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {return authenticationConfiguration.getAuthenticationManager();}/*** 定义密码加密器,采用 BCrypt 算法*/@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
}
解析说明
  • 忽略路径的配置
    SecurityConfigProperties 中读取忽略 URL 列表,通过 antMatchers(...).permitAll() 放行,不需要进行认证与授权。

  • 授权管理器
    对除忽略路径外的其他请求,调用自定义的 JwtTokenAuthorizationManager 进行权限校验,确保只有拥有权限的用户才能访问相应资源。

  • 无状态策略与安全设置
    配置无状态的 session 管理(STATELESS),同时关闭缓存和 CSRF,适应前后端分离的 RESTful 接口场景。

  • 认证管理器和密码加密器
    分别配置了认证管理器和基于 BCrypt 的密码加密器,保障用户密码的安全存储。

2.2 JwtTokenAuthorizationManager 自定义授权管理器

@Component
public class JwtTokenAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate JwtTokenManagerProperties jwtTokenManagerProperties;private AntPathMatcher antPathMatcher = new AntPathMatcher();@Overridepublic AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext requestAuthorizationContext) {// 获取 HttpServletRequest,提取请求头中的 tokenHttpServletRequest request = requestAuthorizationContext.getRequest();String token = request.getHeader(Constants.USER_TOKEN);if(ObjectUtil.isEmpty(token)){return new AuthorizationDecision(false);}// 使用 JWT 工具类解析 token,获取 ClaimsClaims claims = JwtUtil.parseJWT(jwtTokenManagerProperties.getBase64EncodedSecretKey(), token);if(ObjectUtil.isEmpty(claims)){return new AuthorizationDecision(false);}// 从 token 中解析出当前用户信息,并转为 UserVo 对象UserVo userVo = JSONUtil.toBean(String.valueOf(claims.get("currentUser")), UserVo.class);// 从 Redis 缓存中获取该用户的访问权限 URL 列表String accessUrlsCacheKey = CacheConstants.ACCESS_URLS_CACHE + userVo.getId();String accessUrlsJson = redisTemplate.opsForValue().get(accessUrlsCacheKey);List<String> accessUrls = null;if(StringUtils.isNotEmpty(accessUrlsJson)){accessUrls = JSONUtil.toList(accessUrlsJson, String.class);}// 构造当前请求的标识,例如 "GET/nursing_project/**"String targetUrl = request.getMethod() + request.getRequestURI();// 遍历缓存中保存的权限 URL,使用 AntPathMatcher 判断当前请求是否匹配for (String url : accessUrls) {if(antPathMatcher.match(url, targetUrl)){return new AuthorizationDecision(true);}}// 不匹配则返回拒绝访问,系统将自动返回 403 状态码return new AuthorizationDecision(false);}
}
解析说明
  • Token 提取与解析
    从请求头中获取 JWT token,利用 JwtUtil.parseJWT 方法进行解析,获取 Claims。如果 token 无效或解析失败,直接拒绝访问。

  • 用户信息与权限获取
    从 Claims 中提取包含的用户信息,并借助 Redis 缓存,根据用户 ID 获取其允许访问的 URL 列表。这样做的好处是可以动态更新用户权限,无需重启服务。

  • 权限校验
    构造当前请求的标识(HTTP 方法 + 请求 URI),利用 AntPathMatcher 与缓存中的 URL 模式进行匹配,若有任一匹配成功,则返回授权通过。

2.3 SecurityConfigProperties 配置类

@Slf4j
@Data
@ConfigurationProperties(prefix = "zzyl.framework.security")
@Configuration
public class SecurityConfigProperties {/*** 默认密码*/String defaulePassword;/*** 白名单列表(公开接口)*/private List<String> publicAccessUrls;/*** 忽略列表(无需认证的接口)*/private List<String> ignoreUrl;
}
解析说明
  • 配置属性注入
    通过 @ConfigurationProperties 注解,将配置文件中以 zzyl.framework.security 为前缀的配置映射到该类属性上,方便在 Security 配置中动态读取忽略的 URL 列表和其他安全相关的配置项。

  • 属性用途

    • defaulePassword:项目中预设的默认密码(可用于测试或初始化)。
    • publicAccessUrlsignoreUrl:分别定义了公开访问与无需认证的接口列表,保证不同接口的访问策略灵活配置。

三、总结

学习收获

  • 无状态认证思路
    通过 JWT 结合 Redis 实现了无状态的权限校验,既避免了 session 的管理压力,也便于集群部署下的权限动态更新。

  • 灵活的权限控制
    自定义 JwtTokenAuthorizationManager 根据用户缓存的权限列表动态校验请求,利用 AntPathMatcher 实现了路径模式匹配,提升了系统的灵活性与可扩展性。

  • 配置与解耦
    将忽略路径和其他安全配置集中管理(通过 SecurityConfigProperties),使得代码更具可维护性,方便在不同环境下进行调整。

http://www.lryc.cn/news/531668.html

相关文章:

  • 5. k8s二进制集群之ETCD集群部署
  • MV结构下设置Qt表格的代理
  • 二维数组 C++ 蓝桥杯
  • 【Linux】文件描述符
  • 大语言模型的个性化综述 ——《Personalization of Large Language Models: A Survey》
  • AI 编程工具—Cursor进阶使用 Agent模式
  • 【AI大模型】DeepSeek API大模型接口实现
  • Qt展厅播放器/多媒体播放器/中控播放器/帧同步播放器/硬解播放器/监控播放器
  • Kafka分区策略实现
  • 【归属地】批量号码归属地查询按城市高速的分流,基于WPF的解决方案
  • 为AI聊天工具添加一个知识系统 之78 详细设计之19 正则表达式 之6
  • 使用Java操作Redis数据类型的详解指南
  • 一表总结 Java 的3种设计模式与6大设计原则
  • Hive on Spark优化
  • Java集合面试总结(题目来源JavaGuide)
  • 计算机网络 应用层 笔记1(C/S模型,P2P模型,FTP协议)
  • ES6基础内容
  • DeepSeek本地部署的一些使用体会
  • 鲸鱼算法 matlab pso
  • 013-51单片机红外遥控器模拟控制空调,自动制冷制热定时开关
  • 在Vue3 + Vite 项目中使用 Tailwind CSS 4.0
  • Leetcode—922. 按奇偶排序数组 II【简单】
  • 一个开源 GenBI AI 本地代理(确保本地数据安全),使数据驱动型团队能够与其数据进行互动,生成文本到 SQL、图表、电子表格、报告和 BI
  • 使用Posix共享内存区实现进程间通信
  • 家政预约小程序12服务详情
  • 【C语言】指针详细解读2
  • MongoDB 聚合
  • LabVIEW涡轮诊断系统
  • 机器学习在地震预测中的应用
  • 总结11..