Spring Security 自定义后台权限过滤的方案
535 字
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),并批量替换中文注释、按模块分组、优化布局的完整流程。
4
Firefly 代码块示例
文章示例 在Firefly中使用表达性代码的代码块在 Markdown 中的外观。
5
Firefly 布局系统详解
博客指南 深入了解 Firefly 的布局系统,包括侧边栏布局(左侧/双侧)和文章列表布局(列表/网格),以及自适应网格列数。
随机文章 随机推荐