RBAC实现授权

RBAC分为两种方式:

基于角色的访问控制(Role-Based Access Control)

基于资源的访问控制(Resource-Based Access Control)

角色的访问控制(Role-Based Access Control)是按角色进行授权,比如:主体的角色为总经理可以查询企业运营报表,查询员工工资信息等,访问控制流程如下:

RBAC实现授权_第1张图片

根据上图中的判断逻辑,授权代码可表示如下:

Java
if(主体.hasRole("总经理角色id")){
查询工资
}

 当需要修改角色的权限时就需要修改授权的相关代码,系统可扩展性差。

基于资源的访问控制(Resource-Based Access

Control)是按资源(或权限)进行授权,比如:用户必须具有查询工资权限才可以查询员工工资信息等,访问控制流程如下:

RBAC实现授权_第2张图片

根据上图中的判断,授权代码可以表示为:

Java
if(主体.hasPermission("查询工资权限标识")){
    查询工资
}

优点:系统设计时定义好查询工资的权限标识,即使查询工资所需要的角色变化为总经理和部门经理也不需要修改授权代码,系统可扩展性强。

我们项目使用基于资源的访问控制:

这个主要就是通过下面注解来实现的

 这个注解使用条件就是我们的微服务·必须使用springscruty 也就是要引入相关的坐标。

使用这个注解的原理是什么呢,当我们携带令牌访问微服务的上面资源的时候,我们springscruty就会比较我们我们注解中的授权信息是否在令牌中的授权信息列表中,如果不在那么就会报错。

权限系统的实现过程。

权限系统的数据模型

RBAC实现授权_第3张图片

 

说明如下:

xc_user:用户表,存储了系统用户信息,用户类型包括:学生、老师、管理员等

xc_role:角色表,存储了系统的角色信息,学生、老师、教学管理员、系统管理员等。

xc_user_role:用户角色表,一个用户可拥有多个角色,一个角色可被多个用户所拥有

xc_menu:模块表,记录了菜单及菜单下的权限

xc_permission:角色权限表,一个角色可拥有多个权限,一个权限可被多个角色所拥有

 

查询用户所拥有的权限

例子:

SELECT * FROM xc_menu WHERE id IN(
    SELECT menu_id FROM xc_permission WHERE role_id IN(
        SELECT role_id FROM xc_user_role WHERE user_id = '49'
    )
)

 在资源上面加上注解,指定权限

 在生成令牌之前,对权限信息进行赋值

Java
//查询用户身份
public UserDetails getUserPrincipal(XcUserExt user){
    String password = user.getPassword();
    //查询用户权限
    List xcMenus = menuMapper.selectPermissionByUserId(user.getId());
    List permissions = new ArrayList<>();
    if(xcMenus.size()<=0){
        //用户权限,如果不加则报Cannot pass a null GrantedAuthority collection
        permissions.add("p1");
    }else{
        xcMenus.forEach(menu->{
            permissions.add(menu.getCode());
        });
    }
    //将用户权限放在XcUserExt中
    user.setPermissions(permissions);

    //为了安全在令牌中不放密码
    user.setPassword(null);
    //将user对象转json
    String userString = JSON.toJSONString(user);
    String[] authorities = permissions.toArray(new String[0]);
    UserDetails userDetails = User.withUsername(userString).password(password).authorities(authorities).build();
    return userDetails;

}

 对于细粒度的权限控制我们只能自己实现了。如下

我的课程,教学机构只允许查询本教学机构下的课程信息。

我的选课,学生只允许查询自己所选课。

如何实现细粒度授权?

细粒度授权涉及到不同的业务逻辑,通常在service层实现,根据不同的用户进行校验,根据不同的参数查询不同的数据或操作不同的数据。

实现方式之一 使用sql拼装查询语句

 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
 //机构id
 queryWrapper.eq(CourseBase::getCompanyId,companyId);

你可能感兴趣的:(java,开发语言)