SpringSecurity实现动态加载权限信息的方法

 更新时间:2022年01月05日 14:50:44   作者:MMM_Demon  
这篇文章主要介绍了SpringSecurity实现动态加载权限信息,本文给大家介绍的非常详细,对大家的学习或工作具有一定需要的朋友可以参考下

①数据库中资源与角色对应关系,以及角色和用户对应关系如下图所示:

 ②实现FilterInvocationSecurityMetadataSource类

(1)List<Menu> menus = menuService.getMenusWithRoles();这个是你自己的资源对应角色的查询方法。

(2)重写的support方法都返回true

@Configuration
public class MyFilterInvocation implements FilterInvocationSecurityMetadataSource {
 
    @Autowired
    private MenuService menuService;
 
    AntPathMatcher antPathMatcher = new AntPathMatcher();
 
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        String requestUrl = ((FilterInvocation) object).getRequestUrl();
        List<Menu> menus = menuService.getMenusWithRoles();
        //- 遍历数据库的url,看请求路径是否与其匹配
        for (Menu menu : menus) {
            //- 如果请求路径和数据库的路径匹配
            if (antPathMatcher.match(menu.getUrl(),requestUrl)){
                //- 访问该路径需要的角色
                List<Role> roles = menu.getRoles();
                String[] strs = new String[roles.size()];
                for (int i = 0; i < roles.size(); i++) {
                    strs[i] = roles.get(i).getName();
                }
                return SecurityConfig.createList(strs);
            }
        }
        //- 如果请求路径和数据库的所有路径都不匹配,说明这个资源是登录后即可访问的
        //- 用户登录即可访问,相当于在SecurityConfig中配置了.anyRequest().authenticated()
        return SecurityConfig.createList("ROLE_LOGIN");
    }
 
    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }
 
    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}

 

 

③实现AccessDecisionManager

重写的support方法都返回true

@Configuration
public class MyDecisionManager implements AccessDecisionManager {
 
 
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        for (ConfigAttribute configAttribute : configAttributes) {
            String needRole = configAttribute.getAttribute();
            if ("ROLE_LOGIN".equals(needRole)) {
                //- 用户登录即可访问,相当于在SecurityConfig中配置了.anyRequest().authenticated()
                if (authentication instanceof AnonymousAuthenticationToken) {
                    throw new AccessDeniedException("尚未登录,请先登录");
                } else {
                    return;
                }
            }
            
            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
            //这里我写的是只要访问该资源的用户具有`访问该资源所需要角色`的其中一个即可
            for (GrantedAuthority authority : authorities) {
                if (authority.getAuthority().equals(needRole)) {
                    return;
                }
            }
        }
        throw new AccessDeniedException("权限不足,请联系管理员");
    }
 
    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }
 
    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}

④到SecurityConfig配置类中完成相应配置

    @Autowired
    private MyDecisionManager myDecisionManager;
    
    @Autowired
    private  MyFilterInvocation myFilterInvocation;
 
     @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        object.setAccessDecisionManager(myDecisionManager);
                        object.setSecurityMetadataSource(myFilterInvocation);
                        return object;
                    }
                });
 
            http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler());
 
    }
 
 
    @Bean
    MyAccessDeniedHandler myAccessDeniedHandler(){
        return new MyAccessDeniedHandler();
    }

⑤可选,实现AccessDeniedHandler

public class MyAccessDenied implements AccessDeniedHandler {
 
    @Override
    public void handle(HttpServletRequest req, HttpServletResponse resp, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        resp.setContentType("application/json;charset=utf-8");
        PrintWriter pw = resp.getWriter();
        pw.write(new ObjectMapper().writeValueAsString(RespBean.error("权限不够,请联系管理员")));
        pw.flush();
        pw.close();
    }
}

到此这篇关于SpringSecurity实现动态加载权限信息的文章就介绍到这了,更多相关SpringSecurity动态加载权限内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java基于Socket实现简单的多线程回显服务器功能示例

    Java基于Socket实现简单的多线程回显服务器功能示例

    这篇文章主要介绍了Java基于Socket实现简单的多线程回显服务器功能,结合实例形式分析了java使用socket进行多线程数据传输的相关操作技巧,需要的朋友可以参考下
    2017-08-08
  • java合成模式之神奇的树结构

    java合成模式之神奇的树结构

    这篇文章主要介绍了java合成模式,文中运用大量的代码进行详细讲解,希望大家看完本文后能学习到相关的知识,需要的朋友可以参考一下
    2021-08-08
  • JEE与Spring Boot代码性能比较分析

    JEE与Spring Boot代码性能比较分析

    JavaEE与Spring Boot其实很难比较测试,前者适合单体SOA架构,后者适合微服务,但是还是有好事者把两者放在一起比较性能。这篇文章主要介绍了JEE与Spring Boot代码性能比较,需要的朋友可以参考下
    2018-11-11
  • Java 二分查找算法的实现

    Java 二分查找算法的实现

    这篇文章主要介绍了Java 如何实现二分查找算法,帮助大家更好的理解和学习Java 算法,感兴趣的朋友可以了解下
    2020-09-09
  • mybatis-plus 批量插入示例代码

    mybatis-plus 批量插入示例代码

    正常我们使用mybatis-plus插入的时候,首先想到的是saveBatch方法,不过看了下打印出来的sql和底层代码,才发现它并不是真正的批量插入这篇文章主要介绍了mybatis-plus 批量插入示例,需要的朋友可以参考下
    2023-07-07
  • 解决springboot生成bean名称冲突(AnnotationBeanNameGenerator)

    解决springboot生成bean名称冲突(AnnotationBeanNameGenerator)

    这篇文章主要介绍了解决springboot生成bean名称冲突(AnnotationBeanNameGenerator),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Mybatis多表关联查询的实现(DEMO)

    Mybatis多表关联查询的实现(DEMO)

    本节要实现的是多表关联查询的简单demo。场景是根据id查询某商品分类信息,并展示该分类下的商品列表,需要的朋友可以参考下
    2017-02-02
  • 深入浅出讲解Spring框架中依赖注入与控制反转及应用

    深入浅出讲解Spring框架中依赖注入与控制反转及应用

    依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例
    2022-03-03
  • java简单冒泡排序实例解析

    java简单冒泡排序实例解析

    这篇文章主要为大家详细介绍了java简单冒泡排序实例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • springboot利用redis、Redisson处理并发问题的操作

    springboot利用redis、Redisson处理并发问题的操作

    这篇文章主要介绍了springboot利用redis、Redisson处理并发问题的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06

最新评论