六、SpringSecurity实现动态权限控制

2023-10-28

前面已经实现了登陆,即认证,下面是登陆之后的鉴权(即某些角色只能访问特定的资源)

/**
 * @auther Mr.Liao
 * @date 2019/8/20 20:24
 */
@Component
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
    @Autowired
    private MenuMapper menuMapper;
    
    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        //获取请求的url
        String requestUrl = ((FilterInvocation) object).getRequestUrl();
        //获取当前请求需要的角色信息,拿url去menu表中匹配,查看是访问的那个menu下的资源,根据menuId 获取到role信息
        List<Menu> menuList = menuMapper.findAllMenu();
        for (Menu menu : menuList) {
            //如果请求的路径包含在某个menu的url中,且能访问该资源的角色信息存在
            if (antPathMatcher.match(menu.getUrl(),requestUrl) && menu.getRoles().size() > 0) {
                List<Role> roles = menu.getRoles();
                int size = roles.size();
                //定义一个数组,来接收能访问该资源的角色
                String[] roleNameArray = new String[size];
                for (int i = 0; i < size; i++) {
                    roleNameArray[i] = roles.get(i).getRoleAuthority();
                }
                return SecurityConfig.createList(roleNameArray);
            }
        }
        //如果遍历完menu之后没有匹配上,说名访问该资源不需要权限信息,设置一个登陆就能访问的角色
        return SecurityConfig.createList("ROLE_login");
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}
/**
 * @auther Mr.Liao
 * @date 2019/8/20 21:18
 */
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        Iterator<ConfigAttribute> iterator = configAttributes.iterator();
        while (iterator.hasNext()){
            ConfigAttribute configAttribute = iterator.next();
            //访问该请求url需要的角色信息
            String needRole = configAttribute.getAttribute();
            //如果只是登陆就能访问,即没有匹配到资源信息
            if ("ROLE_login".equals(needRole)){
                //判断是否登陆,没有登陆则authentication是AnonymousAuthenticationToken接口实现类的对象
                if (authentication instanceof AnonymousAuthenticationToken){
                    throw new BadCredentialsException("未登录");
                } else return;
            }
            //如果匹配上了资源信息,就拿登陆用户的权限信息来对比是否存在于已匹配的角色集合中
            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;
    }
}
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        RespBean respBean = new RespBean(403, "权限不足", e.getMessage());
        out.write(new ObjectMapper().writeValueAsString(respBean));
        out.flush();
        out.close();
    }
}

配置:

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserLoginService userLoginService;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    @Autowired
    private SuccessHandler successHandler;
    @Autowired
    private FailureHandler failureHandler;
    @Autowired
    private ImageCodeFilter imageCodeFilter;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private MySecurityMetadataSource mySecurityMetadataSource;
    @Autowired
    private MyAccessDecisionManager myAccessDecisionManager;
    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;

    @Bean//PersistentTokenRepository记住我功能的工具类
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        return tokenRepository;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userLoginService)
                .passwordEncoder(bCryptPasswordEncoder);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers( "/login_p.html", "/authentication/request","/favicon.ico","/code/image");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(imageCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setSecurityMetadataSource(mySecurityMetadataSource);
                        o.setAccessDecisionManager(myAccessDecisionManager);
                        return o;
                    }
                })
                .and()
                    //表单登陆配置
                    .formLogin()
                    .loginPage("/authentication/request").loginProcessingUrl("/user/login")
                    .usernameParameter("username").passwordParameter("password")
                    .successHandler(successHandler).failureHandler(failureHandler)
                    .permitAll()
                .and()
                    //记住我配置
                    .rememberMe()
                    .tokenRepository(persistentTokenRepository())
                    .tokenValiditySeconds(20)
                    .userDetailsService(userLoginService)
                .and()// 关闭跨站请求伪造防护
                    .csrf().disable()
                    .exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);
    }
}

测试接口:

@RestController
public class TestController {
    @GetMapping("/emp/basic/test")
    public String test1(){
        return "员工资料接口";
    }

    @GetMapping("/emp/recruitment/test")
    public String test2(){
        return "员工招聘接口";
    }

    @GetMapping("/salary/change/test")
    public String test3(){
        return "工资调整接口";
    }

    @GetMapping("/salary/statistics/test")
    public String test4(){
        return "工资统计接口";
    }

    @GetMapping("/per/evaluation/test")
    public String test5(){
        return "业绩考核接口";
    }

    @GetMapping("/per/statistics/test")
    public String test6(){
        return "业绩统计接口";
    }

    @GetMapping("/test")
    public String test7(){
        return "登陆就能访问的接口";
    }
}

在这里插入图片描述
登陆张三
在这里插入图片描述
访问结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
修改用户的权限信息时,将用户和角色的id添加到user_role表中,调整角色能访问的资源信息时,将关联的角色和资源信息添加到role_menu表中

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

六、SpringSecurity实现动态权限控制 的相关文章

随机推荐

  • LinuxMint上硬盘重装LinuxMint(理论上ubuntu也行)

    主要思路是通过修改引导程序 grub2 的配置文件 boot grub grub cfg 使计算机开机后引导硬盘中存放的系统镜像文件 iso 步骤 1 将下载好的系统镜像文件放入硬盘中一个不会被格式化的分区中 为了方便我直接放在了sda1的
  • C语言可以开发哪些项目?

    C语言是我们大多数人的编程入门语言 对其也再熟悉不过了 不过很多初学者在学习的过程中难免会出现迷茫 比如 不知道C语言可以开发哪些项目 可以应用在哪些实际的开发中 这些迷茫也导致了我们在学习的过程中不知道如何学 学什么 所以 总结这个列表
  • treeSelect节点搜索

    antd中treeSelect的filterTreeNode用法 节点搜索 以下图为例 树形搜索展开后 有以下几个选项 如果我想要搜索其中 产品中心 那直接搜索关键词 产品 即可 我搜索后并未显示我想要的结果 而是为空 这就需要用到 fil
  • 总结JS 常用函数

    希望本文总结的内容能给各位看官带来焕然一新的感觉 另外 如果你们有什么值得推荐的js技巧 欢迎在评论中补充 我可以收纳在本文中 PS 此文档会持续新增内容 Ajax请求 jquery ajax函数 我自己封装了一个ajax的函数 代码如下
  • sudo 之后 unable to resolve host的问题解决办法

    gedit etc hosts 127 0 0 1 localhost 127 0 0 1 Masterback或者其他 把后面的Masterback 或者其他改成新的主机名 应该是最近修改过主机名 也就是用户名 后面的部分
  • _WIN32和_WIN64区别

    WIN32 是一个预定义的宏 用于判断当前编译环境是否为 Windows 操作系统 当使用 MSVC 编译器编译 Windows 应用程序时 无论是 32 位还是 64 位的 Windows 环境 WIN32 宏都会被定义 你可以使用条件编
  • 蓝桥杯2021年第十二届国赛真题-和与乘积

    题目描述 给定一个数列 A a1 a2 an 问有多少个区间 L R 满足区间内元素的乘积等于他们的和 即 aL aL 1 aR aL aL 1 aR 输入格式 输入第一行包含一个整数 n 表示数列的长度 第二行包含 n 个整数 依次表示数
  • SetTimer在无窗口和有窗口线程的使用 .

    今天犯了一个粗心的错误 在无窗口线程中 SetTimer中设置计时器ID 而WM TIMER消息响应函数中得到的计时器ID却不是之前设置的计时器ID 111902 cpp Defines the entry point for the co
  • Prepo —— 图标转化器

    Prepo for mac是Mac os平台上的一款非常不错的Mac图像处理软件 Prepo for mac基于Mac和iOS的一款免费且方便的图标转化器 它可以帮助设计师快速的导出各种尺寸的图标 设计师通过Prepo把任何格式的图片文件转
  • img引入的svg图片,悬浮时怎么修改颜色?

    实现效果 鼠标悬浮在这一行 让这行的文字和svg图片颜色发生变化 因为是用 img标签引入页面 使用fill属性是无效的 css核心代码 active hover transform scale 0 98 img filter drop s
  • Transaction silently rolled back because it has been marked as rollback-only Spring事务嵌套问题

    Transaction silently rolled back because it has been marked as rollback only Spring 事务嵌套问题 添加命令 catch中添加 TransactionAspe
  • Springboot升级到2.x后gridFsTemplate.findOne(query)返回类型由GridFSDBFile改为GridFSFile导致的问题

    问题描述 gridFsTemplate findOne query 返回类型由GridFSDBFile改为GridFSFile导致的问题 文件下载时下面的代码不可用 GridFSDBFile gridFSDBFile new GridFSD
  • java.lang.NoClassDefFoundError: javax/servlet/ServletContext(可能报错原因,不可盖全)

    例如一下jar包版本低 提高版本即可 version 5 0 5RELEASE
  • ArcGIS中统计渔网中栅格人口密度

    文章目录 前言 一 人口数据获取 来源一 中科院地理所公开数据集 来源二 WorldPop数据集 二 人口格网统计步骤 1 创建渔网 2 人口数据处理 2 1 栅格转点 2 2 空间插值 处理人口缺失数据 2 3 空间连接 渔网人口统计 总
  • IGBT简介、结构及原理

    所谓IGBT 绝缘栅双极型晶体管 是由 BJT 双极结型晶体三极管 和 MOS 绝缘栅型场效应管 组成的复合全控型 电压驱动式 功率半导体器件 其具有自关断的特征 简单讲 是一个非通即断的开关 IGBT没有放大电压的功能 导通时可以看做导线
  • ubuntu 安装微信(wechat)

    软件介绍 Wine Wine Is Not an Emulator Wine不是一个模拟器 的缩写 是一个能够在多种 POSIX compliant 操作系统 诸如 Linux Mac OSX 及 BSD 等 上运行 Windows 应用的
  • java动态上传图片_Java实现图片文件上传

    Java实现后台图片上传 将上传图片的接口进行分层 便于维护接口 接口部分 interface 将接口分为单图片上传以及多图片上传 public interface FileUploadService 单图片上传 PicUploadResu
  • 服务器装win10性能怎样,Win10 藏着不给人看的卓越性能模式到底对电脑有什么影响?...

    未来Win10的功能与稳定性趋于完善 其流行趋势会越来越大 许多游戏玩家选择也会选择 Win10 其独有的游戏模式与Xbox游戏录制功能也是对游戏的一大支持所在 今天小编就带大家来简单测试一下Win10 的卓越性能模式对游戏以及电脑性能的影
  • DispatcherServlet最全详解

    文章目录 DispatcherServlet最全详解 DispatcherServlet族谱 一 语言总结 1 DispatcherServlet初始化 2 DispatcherServlet调用组建处理请求 二 DispatcherSer
  • 六、SpringSecurity实现动态权限控制

    前面已经实现了登陆 即认证 下面是登陆之后的鉴权 即某些角色只能访问特定的资源 auther Mr Liao date 2019 8 20 20 24 Component public class MySecurityMetadataSou