框架开源地址:

青锋开源架构-springboot2.6.x+vue3-antdesign-vite: 青锋-springboot2.6.x+vue3-antdesign-vite开源架构,实现了系统管理模块、权限控制模块(菜单权限、功能按钮权限、数据权限)、代码生成器(单表、树表)、quartz动态定时器等功能。

权限访问控制讲解

GrantedAuthority接口

Spring Security中有一些概念和实现,例如GrantedAuthority用于获得授权来授权/控制访问权限的接口。

我希望对允许的操作(例如userList或user:del)进行允许,这些操作将允许管理员(具有role ROLE_ADMIN)使用。

通过查看org.springframework.security.core.userdetails.UserDetails了身份验证提供程序引用的DAO中使用的接口,该接口消耗了User(请注意最后的GrantedAuthority):

public User(String username, 
            String password, 
            boolean enabled, 
            boolean accountNonExpired,
            boolean credentialsNonExpired, 
            boolean accountNonLocked, 
            Collection<? extends GrantedAuthority> authorities)

当用户执行登录验证之后,查询对应的权限集合authorities,将权限集合返回到User对象中。

获取用户权限集合

我们可以通过userDetailsService.loadUserByUsername("admin").getAuthorities()获取用户的权限信息,这里的权限信息就是上面讲解的authorities设置的权限信息。

userDetailsService.loadUserByUsername("admin").getAuthorities()

项目中如何使用?

配置权限身份认证

我们在SecurityConfigure中设置权限的身份认证,如下:

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

加载用户权限

我们通过查询当前登录用户的权限信息,并将权限信息返回到User中。

 List<GrantedAuthority> grantedAuthorityList = AuthorityUtils.commaSeparatedStringToAuthorityList(permissions);
 AuthUser authUser = new AuthUser(uPd.get("login_name").toString()+":"+uPd.get("id").toString()+":"+organize_id, uPd.get("login_password").toString(), true, true, true, notLocked,
                            grantedAuthorityList);

AuthUser继承了User接口,我们通过查看User构造方法如下:

详细代码如下:

 @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        PageData pd = new PageData();
        if(username.contains(":")){
            pd.put("login_name",username.split(":")[0]);
        }else{
            pd.put("login_name",username);
        }
        PageData uPd = userManager.findUserInfo(pd);
        System.out.println(uPd);
        if(Verify.verifyIsNotNull(uPd)){
            System.out.println(uPd.get("status"));
            if(uPd.get("status").equals("2")){
                throw new UsernameNotFoundException("账号已休眠,请联系管理员");
            }else{
                if(uPd.get("status").equals("0")){
                    //查询当前用户组织
                    pd.put("user_id",uPd.get("id"));
                    PageData orgPd = userManager.findUserOrganizeInfo(pd);
                    String organize_id = "";
                    if(Verify.verifyIsNotNull(orgPd)){
                        organize_id = orgPd.get("organize_id")+"";
                    }
                    //登录成功
                    pd.put("user_id",uPd.get("id"));
                    String permissions = userManager.findUserPermissions(pd);
//                    System.out.println("===================================查询出来数据权限==============================");
//                    System.out.println(permissions);
                    boolean notLocked = false;
                    if (StringUtils.equals("0", uPd.get("status").toString()))
                        notLocked = true;

                    List<GrantedAuthority> grantedAuthorityList = AuthorityUtils.commaSeparatedStringToAuthorityList(permissions);
                    AuthUser authUser = new AuthUser(uPd.get("login_name").toString()+":"+uPd.get("id").toString()+":"+organize_id, uPd.get("login_password").toString(), true, true, true, notLocked,
                            grantedAuthorityList);
                    return transToAuthUser(authUser,uPd);
                }else if(uPd.getString("status").equals("1")){
                    throw new UsernameNotFoundException("账号已禁用,请联系管理员");
                }else if(uPd.getString("status").equals("2")){
                    throw new UsernameNotFoundException("账号已休眠,请联系管理员");
                }
            }
            return null;
        }else{
            throw new UsernameNotFoundException("登录名称不存在,请重新输入。");
        }
    }

权限SQL数据

通过SQL可以看到,数据权限perms的权限是通过父节点菜单的权限标识符:按钮功能权限标识符,比如用户的查看、新增、编辑、删除方法:

user:info
user:add
user:edit
user:del

请求方法增加权限控制

请求方法中,通过增加注解:@PreAuthorize("hasAnyAuthority('xxx:xxx')")进行权限控制:

@PreAuthorize("hasAnyAuthority('xxx:xxx')")

下面以系统用户权限控制方法进行讲解:

  /**
     * @title listPage
     * @description 查询数据分页列表
     * @author Administrator
     * @updateTime 2022/1/19 0019 23:41
     */
    @GetMapping("/listPage")
    @PreAuthorize("hasAnyAuthority('user:info')")
    public MyResponse listPage(QueryRequest queryRequest, Area area) {
        String userParams = SecurityContextHolder.getContext().getAuthentication().getName();
        return new MyResponse().data(dataTable);
    }

    /**
     * @title save
     * @description 保存数据
     * @author Administrator
     * @updateTime 2022/1/19 0019 23:41
     */
    @PostMapping
    @PreAuthorize("hasAnyAuthority('user:add')")
    public void save(@Valid @RequestBody Area area,HttpServletResponse response) throws Exception {
        this.writeJson(response,json);
    }

    /**
     * @title update
     * @description 更新数据
     * @author Administrator
     * @updateTime 2022/1/19 0019 23:41
     */
    @PutMapping
    @PreAuthorize("hasAnyAuthority('user:edit')")
    public void update(@Valid @RequestBody Area area,HttpServletResponse response) throws Exception {
        Json json = new Json();
        this.writeJson(response,json);
    }

    /**
     * @title delete
     * @description 删除数据
     * @author Administrator
     * @updateTime 2022/1/19 0019 23:41
     */
    @DeleteMapping("/{ids}")
    @PreAuthorize("hasAnyAuthority('user:del')")
    public void delete(@NotBlank(message = "{required}") @PathVariable String ids,HttpServletResponse response) throws Exception {
        Json json = new Json();
        this.writeJson(response,json);
    }

    /**
     * @title updateStatus
     * @description 更新状态
     * @author Administrator
     * @updateTime 2022/1/19 0019 23:41
     */
    @PostMapping("/updateStatus")
    @PreAuthorize("hasAnyAuthority('user:status')")
    public void updateStatus(@Valid @RequestBody Area area,HttpServletResponse response) throws Exception {
        Json json = new Json();
        this.writeJson(response,json);
    }

菜单和按钮权限标识设置

看到这里,大家可能会有疑问,上面提到的user:add,用户菜单user和添加按钮add在哪里设置的呢?

Logo

前往低代码交流专区

更多推荐