spring-addons进阶从数据库加载权限JPA实现动态GrantedAuthorities检索【免费下载链接】spring-addonsAdditional Spring Boot auto-configuration for OAuth2 / OpenID REST项目地址: https://gitcode.com/gh_mirrors/sp/spring-addonsspring-addons 为 Spring Boot 提供了 OAuth2/OpenID 资源服务器的自动配置本文带你用 JPA 从数据库动态加载用户权限GrantedAuthorities彻底摆脱改角色必须重新发 Token的痛点。通过自定义ClaimSetAuthoritiesConverter扩展点我们可以在几十行代码内实现权限实时生效、角色集中管理的进阶方案适合新手快速上手。为什么需要从数据库加载权限默认情况下JWT 资源服务器的用户角色ROLE_*都写在 Token 的realm_access、roles等 claim 里。这样做有两个麻烦权限变更不及时用户角色调整后必须等 Token 过期重新签发才能生效Token 体积膨胀角色越多JWT 越大每次请求的开销越高。把权限挪到数据库后角色由业务系统自己管理每次请求实时查询、按需生效还能结合缓存把性能损失降到最低。这正是 spring-addons 提供的可插拔扩展点ClaimSetAuthoritiesConverter只要提供一个实现类权限来源就完全由你说了算。核心扩展点ClaimSetAuthoritiesConverter spring-addons 在认证成功后会把 JWT 解析出的 claims 交给一个转换器由它决定当前用户拥有哪些GrantedAuthority。这个接口的定义在spring-addons-starter-oidc模块的com.c4_soft.springaddons.security.oidc.starter.ClaimSetAuthoritiesConverter它只是ConverterMapString, Object, Collection? extends GrantedAuthority的别名——输入是 claims 字典输出是权限集合。你完全可以绕过 claims去数据库里查在官方示例webmvc-jwt-default-jpa-authorities中一个完整的实现只有 30 行左右public class PersistedGrantedAuthoritiesRetriever implements ClaimSetAuthoritiesConverter { private final UserAuthorityRepository authoritiesRepo; public PersistedGrantedAuthoritiesRetriever(UserAuthorityRepository authoritiesRepo) { this.authoritiesRepo authoritiesRepo; } Override Transactional(readOnly true) public SetGrantedAuthority convert(NonNull MapString, Object claims) { final CollectionUserAuthority authorities authoritiesRepo.findByIdUserSubject((String) claims.get(JwtClaimNames.SUB)); return authorities.stream() .map(UserAuthority::getAuthority) .map(SimpleGrantedAuthority::new) .collect(Collectors.toSet()); } }逻辑一目了然从 JWT 中取出用户标识sub去数据库查出该用户的所有权限包装成SimpleGrantedAuthority返回。核心代码就这么多下面我们来一步步搭起来。第一步定义 JPA 实体与仓储含缓存权限表用user_subject authority作为联合主键既保证一个用户一条角色一行也方便按用户批量查询。示例中的实体与仓储位于webmvc-jwt-default-jpa-authorities示例的UserAuthority、UserAuthorityId、UserAuthorityRepository实体采用EmbeddedId联合主键Entity Data public class UserAuthority implements Serializable { EmbeddedId private UserAuthorityId id; private String label; // getAuthority() / getUserSubject() 由 id 委托实现 }仓储继承JpaRepository并给查询方法加上Cacheable避免每次请求都打数据库public interface UserAuthorityRepository extends JpaRepositoryUserAuthority, UserAuthorityId { Cacheable(users-authorities) CollectionUserAuthority findByIdUserSubject(String subject); }第二步注册转换器 Bean接入 spring-addons 只差最后一步——把我们的PersistedGrantedAuthoritiesRetriever注册成 Spring Bean。spring-addons 启动时会自动发现这个 Bean 并替换默认的权限解析逻辑全程零魔法配置Configuration EnableMethodSecurity public class SecurityConfig { Bean ClaimSetAuthoritiesConverter authoritiesConverter(UserAuthorityRepository authoritiesRepo) { return new PersistedGrantedAuthoritiesRetriever(authoritiesRepo); } }同时别忘了两件事在主启动类上加EnableCaching让仓储的Cacheable生效参考示例的WebmvcJwtDefaultJpaAuthorities用PersistenceConfig开启 JPA 与事务管理EnableJpaRepositoriesEnableTransactionManagement。 提示Transactional(readOnly true)放在转换器上保证查询在事务内执行同时只读事务更省资源。第三步路由授权与方法级安全联动 权限从数据库加载后用法和以前完全一致。示例GreetingController中既有 URL 级别的secured-route也有方法级的PreAuthorize(hasRole(AUTHORIZED_PERSONNEL))权限判断全部走 Spring Security 标准机制路由级通过ResourceServerExpressionInterceptUrlRegistryPostProcessor配置/secured-route需要ROLE_AUTHORIZED_PERSONNEL方法级PreAuthorize(hasRole(AUTHORIZED_PERSONNEL))守护/secured-method。也就是说你可以放心沿用现有的hasRole/hasAuthority表达式不用改任何业务代码权限来源已悄然切换为数据库。第四步编写测试验证权限加载 ✅spring-addons 还配套提供了测试模块spring-addons-starter-oidc-test配合WithJwt、WithMockAuthentication注解可以轻松模拟认证。示例中的TestUserAuthorityRepositoryConf用 Mockito 模拟了仓储返回的权限GreetingControllerAnnotatedTest则完整覆盖了无权限 403 / 有权限 200两条路径你可以直接照抄这套测试骨架。总结三步实现数据库权限加载 回顾整个方案spring-addons 让从数据库加载权限变得异常简单建实体定义UserAuthority与UserAuthorityRepository加缓存写转换器实现ClaimSetAuthoritiesConverter用sub查库并返回权限注册 Bean在SecurityConfig中暴露自定义转换器并开启缓存与事务。完整示例代码就在项目的webmvc-jwt-default-jpa-authorities目录对应代码文件PersistedGrantedAuthoritiesRetriever.java、SecurityConfig.java、UserAuthorityRepository.java把数据库换成 PostgreSQL、MySQL 也只需改一行连接配置。如果希望权限在用户在线时就能实时变更、又不想频繁改 Token 签发策略这套 JPA 方案就是你的终极答案。【免费下载链接】spring-addonsAdditional Spring Boot auto-configuration for OAuth2 / OpenID REST项目地址: https://gitcode.com/gh_mirrors/sp/spring-addons创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考