【第1期】SpringSecurity基于角色和权限的细粒度接口权限控制

SpringSecurity 细粒度权限控制

一、Role 和 Authority的区别

角色用来表示某一类权限的集合,权限粒度更小,方便细粒度控制

二、创建用户、角色、权限相关表:

CREATE TABLE `common_user` (
  `id` bigint(20) NOT NULL COMMENT '主键id',
  `login_name` varchar(32) CHARACTER SET utf8 NOT NULL COMMENT '登录名称',
  `password` varchar(2048) CHARACTER SET utf8 NOT NULL COMMENT '密码',
  `status` varchar(10) CHARACTER SET utf8 DEFAULT NULL COMMENT '认证状态:SUCCESS-认证通过;FAILED-认证失败;INIT-初始化;LOCKED-锁定;UNLOCKED-自动解锁',
  `phone` varchar(13) CHARACTER SET utf8 DEFAULT NULL COMMENT '手机号',
  `born` date DEFAULT NULL COMMENT '出生日期',
  `fail_count` int(2) DEFAULT NULL COMMENT '失败次数',
  `creator` varchar(20) CHARACTER SET utf8 NOT NULL COMMENT '创建人',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  `modifier` varchar(20) CHARACTER SET utf8 DEFAULT NULL COMMENT '修改人',
  `modify_time` timestamp NULL DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uk_login_name` (`login_name`) USING BTREE COMMENT 'login_name唯一索引',
  KEY `idx_phone` (`phone`) USING BTREE COMMENT 'phone索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

CREATE TABLE `common_user_role` (
  `id` bigint(20) NOT NULL COMMENT '主键id',
  `user_id` bigint(20) NOT NULL COMMENT '用户id',
  `role_id` bigint(20) NOT NULL COMMENT '角色id',
  `creator` varchar(20) NOT NULL COMMENT '创建人',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `modifier` varchar(20) DEFAULT NULL COMMENT '修改人',
  `modify_time` datetime DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_user_role` (`user_id`,`role_id`) USING BTREE COMMENT '用户角色组合索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色表';

CREATE TABLE `common_role` (
  `id` bigint(20) NOT NULL COMMENT '主键id',
  `name` varchar(32) NOT NULL COMMENT '角色名称',
  `desc` varchar(64) DEFAULT NULL COMMENT '角色描述',
  `creator` varchar(20) NOT NULL COMMENT '创建人',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `modifier` varchar(20) DEFAULT NULL COMMENT '修改人',
  `modify_time` datetime DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_name` (`name`) USING BTREE COMMENT '角色名称索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';

CREATE TABLE `common_role_permission` (
  `id` bigint(20) NOT NULL COMMENT '主键id',
  `role_id` bigint(20) NOT NULL COMMENT '角色id',
  `permission_id` bigint(20) NOT NULL COMMENT '权限id',
  `creator` varchar(20) NOT NULL COMMENT '创建人',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `modifier` varchar(20) DEFAULT NULL COMMENT '修改人',
  `modify_time` datetime DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_role_permission` (`role_id`,`permission_id`) USING BTREE COMMENT '角色权限组合索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色权限表';

CREATE TABLE `common_role` (
  `id` bigint(20) NOT NULL COMMENT '主键id',
  `name` varchar(32) NOT NULL COMMENT '角色名称',
  `desc` varchar(64) DEFAULT NULL COMMENT '角色描述',
  `creator` varchar(20) NOT NULL COMMENT '创建人',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `modifier` varchar(20) DEFAULT NULL COMMENT '修改人',
  `modify_time` datetime DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_name` (`name`) USING BTREE COMMENT '角色名称索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';

三、给资源授予权限(角色或权限)

注意:角色 (“ADMIN”,“MEMBER”,“GUEST”),在SpringSecurity中设置时需要添加前缀ROLE_,所以这里存储有2种方案
第一种:数据库存储角色名称,没有ROLE_的前缀,如下图
【第1期】SpringSecurity基于角色和权限的细粒度接口权限控制_第1张图片
那么,在角色加载的时候,需要补上前缀ROLE_
【第1期】SpringSecurity基于角色和权限的细粒度接口权限控制_第2张图片
接口配置角色访问策略时,无需添加ROLE_前缀了,SpringSecurity在进行角色权限判断时会自动加ROLE_前缀,这样配置:
【第1期】SpringSecurity基于角色和权限的细粒度接口权限控制_第3张图片
配置后,当前用户如果登录成功,便有了该接口的访问权限(需要行政区划平铺数据的私信):
【第1期】SpringSecurity基于角色和权限的细粒度接口权限控制_第4张图片

第二种:数据库存储角色的时候就添加ROLE_前缀,这样在角色加载时就无需再添加ROLE_前缀了,不再赘述

三、角色与权限结合起来控制接口的访问权限

例如:角色ROLE必须是MEMBER,并且有权限division:flat_cities才能访问该接口,接口处这样配置:
【第1期】SpringSecurity基于角色和权限的细粒度接口权限控制_第5张图片
当前用户已设置MEMBER角色和division:flat_cities权限,访问试试:
此时,出了点小插曲,登录失效了,这里就是SpringSecurity+RSA+JWT+Redis的权限控制和登录退出控制
【第1期】SpringSecurity基于角色和权限的细粒度接口权限控制_第6张图片
通过接口先登录,获取Token,登录成功后响应的header返回了X-Auth-Token令牌,每次请求携带该令牌即可访问接口,仅仅是允许访问,不代表有权限,权限还是通过角色+权限来控制的
【第1期】SpringSecurity基于角色和权限的细粒度接口权限控制_第7张图片
接下来访问接口:
【第1期】SpringSecurity基于角色和权限的细粒度接口权限控制_第8张图片
如果:把当前用户的角色保留,权限去掉division:flat_cities,会怎样?我这里将权限改错等同于去掉了,因为接口配置的权限是division:flat_cities
在这里插入图片描述
再次携带当前登录用户的Token访问接口,发现就无权访问了:
【第1期】SpringSecurity基于角色和权限的细粒度接口权限控制_第9张图片

二、细粒度的资源控制
authenticated():通过认证的用户都可以访问

permitAll():允许所有人访问,即使未登录

authorizeRequests():更细粒度的控制

access(String): SpEL:Spring表达式

​ .access(“hasRole(‘大师’) AND hasAuthority(‘user:delete’) OR hasIpAddress(‘192.168.0.1’)”)

四、细粒度的资源控制必要的注解

  • 开启注解控制权限模式

@EnableWebSecurity:开启 Spring Security 注解
@EnableGlobalMethodSecurity(prePostEnabled=true):开启全局的细粒度方法级别权限控制功能

几个权限检查注解

@PreAuthorize:方法执行前检查
@PreAuthorize(“hasRole(‘ADMIN’)”)
@PostAuthorize:方法执行后检查,失败抛异常
@PostAuthorize:允许方法调用,但是,如果表达式结果为false抛出异常
@PostAuthorize("returnObject.user.usernameprincipal.username")
@PostFilter:允许方法调用,但是按照表达式过滤方法结果
@PostFilter("returnObject.user.sex
’男’ ")
@PreFilter:允许方法调用,但必须在进入方法前过滤输入值
@Secured:拥有指定角色才可以访问方法
@Secured(‘ADMIN’) 等价于 @PreAuthorize(“hasRole(‘ADMIN’)”)

五、细粒度的资源控制注解中可写的表达式

所有能使用的表达式见下面文档连接:
https://docs.spring.io/spring-security/site/docs/4.0.1.RELEASE/reference/htmlsingle/#el-common-built-in

你可能感兴趣的:(SpringSecurity,RSA,JWT,Redis)