Spring Security 自定义后台权限过滤的方案
505 字
3 分钟
Spring Security 自定义后台权限过滤的方案

大概思路
方案有好几种,比如注解式的 @PreAuthorize("hasRole('ROLE_admin') and hasAnyRole('ROLE_user')"),或者在配置里写 hasRole。
我的其中一种思路
@Service@RequiredArgsConstructorpublic class InyaaAccessDecisionManager implements AuthorizationManager<RequestAuthorizationContext> {
private final SecurityMetadataSource securityMetadataSource;
@Override public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) { Collection<ConfigAttribute> collection = this.securityMetadataSource.getAttributes(context); // 遍历角色 for (ConfigAttribute ca : collection) { // ① 当前url请求需要的权限 String needRole = ca.getAttribute(); if ("ROLE_ANY".equals(needRole)) { return new AuthorizationDecision(true); } else { // ② 当前用户所具有的角色 Collection<? extends GrantedAuthority> authorities = authentication.get().getAuthorities(); for (GrantedAuthority authority : authorities) { if ("ROLE_ANONYMOUS".equals(authority.getAuthority())) { return new AuthorizationDecision(false); } else { return new AuthorizationDecision(true); } } } } return new AuthorizationDecision(false); }}@Service@RequiredArgsConstructorpublic class InyaaFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
private final CacheService cacheService;
/*** * 返回该url所需要的用户权限信息 * * @param object: 储存请求url信息 * @return: null:标识不需要任何权限都可以访问 */ @Override public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { HttpServletRequest request = ((RequestAuthorizationContext) object).getRequest(); Map<String, Collection<ConfigAttribute>> cacheMap = cacheService.getConfigAttributeMap(); for (String url : cacheMap.keySet()) { if (new AntPathRequestMatcher(url).matches(request)) { return cacheMap.get(url); } } throw new AccessDeniedException("当前访问没有权限!"); }
@Override public Collection<ConfigAttribute> getAllConfigAttributes() { return null; }
@Override public boolean supports(Class<?> aClass) { return FilterInvocation.class.isAssignableFrom(aClass); }}AuthorizationManager<RequestAuthorizationContext> 主要是对角色的验证,他加载 FilterInvocationSecurityMetadataSource 接口的数据。而 FilterInvocationSecurityMetadataSource 接口主要是做权限的匹配,其中我用到了缓存来加载所有的权限,然后通过 URL 去匹配。
而缓存内的加载大致如下:
public Map<String, Collection<ConfigAttribute>> getConfigAttributeMap() { if (AuthCache.size() < 1) { List<InyawSysApi> list = inyawSysApiDao.findAll(); for (InyawSysApi api : list) { List<ConfigAttribute> configAttributeList = new ArrayList<>(); ConfigAttribute configAttribute; switch (api.getType()) { case 0 -> configAttribute = new SecurityConfig("ROLE_ANY"); case 1 -> configAttribute = new SecurityConfig("ROLE_LOGIN"); case 2 -> { InyawSysRole role = inyawSysRoleService.getById(api.getId()); configAttribute = new SecurityConfig(role.getRoleKey()); } default -> throw new IllegalStateException("错误的类型: " + api.getType()); } configAttributeList.add(configAttribute); AuthCache.put(api.getUrl(), configAttributeList); } } return AuthCache;}其余就不多解释了,代码水平也一般。大概就是 API 表的 type 字段决定权限类型——当时没想好具体的权限表设计,实际也没这个需求。
最后是配置类
http .authorizeHttpRequests((authorize) -> authorize .anyRequest().access(inyaaAccessDecisionManager) ) .csrf(AbstractHttpConfigurer::disable) .oauth2ResourceServer(httpSecurityOAuth2ResourceServerConfigurer -> httpSecurityOAuth2ResourceServerConfigurer.jwt(Customizer.withDefaults())) .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .exceptionHandling((exceptions) -> exceptions .authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint()) .accessDeniedHandler(new BearerTokenAccessDeniedHandler()) );这个配置类基本是官方 Demo 的 JWT 方案,真正管权限的也就 csrf 前面那几行。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!
Spring Security 自定义后台权限过滤的方案
https://blog.yuxh.cc/posts/spring-security-custom-authorization/相关文章智能推荐
1
一种不错的学习型个人开发者的持续集成方案:GitHub Action
笔记面向个人开发者的轻量级 CI/CD 方案,使用 GitHub Action 实现 Java 项目从代码提交到 Docker 部署的自动化流程。
2
从 Lucky 迁移到 Nginx:我的轻量级反向代理方案
笔记从 Lucky 切到 nginx-ui + Nginx 的过程记录,包含部署方式、DDNS 配置、腾讯云子账号权限和防火墙放行。
3
使用 PowerDesigner 从 MySQL 反向工程生成物理数据模型并优化展示
笔记使用 PowerDesigner 从 MySQL 数据库反向生成物理数据模型(PDM),并批量替换中文注释、按模块分组、优化布局的完整流程。
随机文章随机推荐














