基于RBAC实现权限管理

RBAC

RBAC数据库表

主体

资源

权限

角色

用户角色

角色权限

将资源表和权限表进行合并为权限表

权限

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

主要思想就是访问后台接口的时候判断该用户的角色是否为某某角色,是的话就放行,否则就拒绝访问。

这里我用的jwt,token里存储的由用户角色(ADMIN)

实现方式:自定义注解+拦截器

自定义注解
@Target({ElementType.METHOD})			//注解作用域方法上
@Retention(RetentionPolicy.RUNTIME)		//编译器将注解信息存储与class文件中,由JVM读取
@Documented
public @interface HasRole {
    String[] value() default {};
}
SpringMVC拦截器
@Component
public class AccessControlInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            if (handlerMethod.hasMethodAnnotation(HasRole.class)) {
                // 从request中获取token
                // 解析token获取claims
                // claims就是个map,直接获取用户角色
                String role = claims.get("userRole");
                String[] hasRole = handlerMethod.getMethodAnnotation(HasRole.class).value();
                boolean contains = Arrays.asList(hasRole).contains(role);
                if(!contains){
                    // 不符合条件,可以抛自定义异常,给客户端提示信息
                    return false;
                }
            }
        }
        return true;
    }
}

注意:最后要把拦截器加入到配置里面

这种方式很简单,应对简单的需求很实用,但是复杂的就行不通了


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

主要思想,由于资源是不会变的,我们给角色或者用户分配资源权限后,直接在拦截器里面进行资源权限的校验即可。且有变动的时候基本上不需要改动代码。

用户登录的后把用户的资源权限查出来放到redis里面

实现方式依旧:自定义注解+拦截器

自定义注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HasResourcePermission {
    String value() default "";
}
SpringMVC拦截器
@Component
public class RequestInterceptor implements HandlerInterceptor {
    @Resource
    private RedisTemplate<String,Object> redisTemplate;

        @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            if (handlerMethod.hasMethodAnnotation(HasResourcePermission.class)) {
                String resourcePermissionSign = handlerMethod.getMethodAnnotation(HasResourcePermission.class).value();
                Object resourcePermission = redisTemplate.opsForValue().get("resourcePermission");
                List<String> resourcePermissionList = (List<String>) resourcePermission;
                if (resourcePermissionList.contains(resourcePermissionSign)) {
                    // 不符合条件,可以抛自定义异常,给客户端提示信息
                    return false;
                }
            }
        }
        return true;
    }
}

注意:最后要把拦截器加入到配置里面

基本上就是这样了,也可以根据需求再改,关于数据库表业务会需要加上用户组表的信息。

11-21 22:14