自己开发完整项目一、登录功能-05(动态权限控制)

一、上节回顾

在上一节中,我们介绍了如何通过数据库查询用户的权限,并对方法级别的接口使用注解的方式进行权限控制,之后通过用户携带的tocken进行解析权限,判断是否可以访问。


具体步骤:
1.在查询用户信息的时候将用户权限查询出来,并给前端返回一个tocken。

2.编写一个后端过滤:作用主要是通过自定义的jwt工具将tocken进行解析,将解析出来的权限信息告诉给springsecurity。

3.将自定义的过滤器加载到springsecurity中的过滤器链中。

4.在方法级别的接口上通过@PreAuthorize("hasAnyAuthority('qxgl')")  //需要的权限进行权限控制。

5.访问验证


那么上述方案有一个问题,在真实项目中,接口是非常多的,并且通过注解的方式进行权限控制的话,那么当接口权限发生变化的时候,改动量是非常大的,所以我们需要动态的设置接口权限。

二、动态权限的实现思路

1.每一个页面或者是按钮都有一个访问接口,那么我们就需要在menu表中增加访问接口的字段。

2.编写一个类实现AuthorizationManager接口,在这个接口中,我们需要查询出当前访问接口所需要的权限,然后根据当前用户的权限进行比对,如果有则放行。

2.在springsecurity的配制文件中,添加access配置并传入自定义类

 三、动态权限实现步骤

1..每一个页面或者是按钮都有一个访问接口,那么我们就需要在menu表中增加访问接口的字段。

CREATE TABLE `menu` (
  `id` int NOT NULL COMMENT 'id',
  `menu_name` varchar(255) DEFAULT NULL COMMENT '权限名称',
  `menu_tag` varchar(255) DEFAULT NULL COMMENT '权限标签',
  `parent_id` int DEFAULT NULL COMMENT '父id',
  `menu_type` int DEFAULT NULL COMMENT '权限类型(1:目录,2:菜单,3:按钮)',
  `is_deleted` int DEFAULT NULL COMMENT '是否删除',
  `path` varchar(255) DEFAULT NULL COMMENT '访问路径',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

2.编写一个类实现AuthorizationManager接口,在这个接口中,我们需要查询出当前访问接口所需要的权限,然后根据当前用户的权限进行比对,如果有则放行。

 

package com.ljy.myspringbootlogin.filter;


/**
 * 这个类主要作用:实现动态权限
 * 1.实现AuthorizationManager
 * 2.重写其中的check()方法
 * 3.获取前端的请求路径(其中登录接口不需要认证)
 * 4.根据请求路径查询所需要的权限
 */


/**
 * RequestAuthorizationContext  我们需要从这里取出请求接口路径
 */

import com.ljy.myspringbootlogin.model.MenuModel;
import com.ljy.myspringbootlogin.service.IMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Component
public class SpringSecurityAuyhorizationManager implements AuthorizationManager<RequestAuthorizationContext> {
@Autowired
    IMenuService iMenuService;

    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext requestAuthorizationContext) {
       //获取前端的请求路径
        HttpServletRequest request = requestAuthorizationContext.getRequest();
        String requestURI = request.getRequestURI();
        StringBuffer requestURL = request.getRequestURL();
        System.out.println("uri: "+requestURI);
        System.out.println("url: "+requestURL);

        //登录接口不需要认证
        if("/sys/login".equals(requestURI)){
            return new AuthorizationDecision(true);
        }

        //根据前端的请求路径查询menu
        MenuModel menuByPath = iMenuService.getMenuByPath(requestURI);
        if(menuByPath==null){
            return new AuthorizationDecision(false);
        }

        //获取所需要的权限
        String menuTag = menuByPath.getMenuTag();
        System.out.println("路径权限:"+menuTag);
        if(menuTag == null || menuTag.trim().equals("")){
            return new AuthorizationDecision(true);
        }

        //和用户的权限集合进行判断
        Collection<? extends GrantedAuthority> authorities = authentication.get().getAuthorities();
        for (GrantedAuthority authority : authorities) {
            String userParam = authority.getAuthority();
            System.out.println("用户权限:"+userParam);
            if(userParam.equals(menuTag)){
                return new AuthorizationDecision(true);
            }
        }

        return new AuthorizationDecision(false);

    }
}

3.在springsecurity的配置文件中配置

 

http.authorizeHttpRequests()
                .antMatchers("/sys/**").permitAll()
//                .anyRequest().authenticated();
        .anyRequest().access(springSecurityAuyhorizationManager);   //动态实现权限

4.测试

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值