Skip to content

数据权限配置

TIP

更详细的内容可以查看 身份识别与访问管理 下的具体模块,有更详细的说明。

功能

  • 数据字段字段加密解密,在数据库中存储AES加密后的内容,预防信息被脱裤后导致信息泄露
  • 返回数据信息敏感信息脱敏,后端信息返回给前端时,对一些敏感信息进行脱敏,如密码、秘钥等,防止保密信息被流出,可以结合数据字段加密一起使用
  • 数据范围权限控制,通过在线配置,实现不同的用户可以查询到不同范围的数据,更好的实现数据分级管理
  • 查询字段权限控制,通过对字段配置权限码,可以实现不同的用户查询到不同的数据字段,更好的实现数据分级管理

字段加密解密

WARNING

只有通过通过MyBatis-Plus对整个对象进行保存或更新时才生效,通过Wrapper进行局部更新时会导致字段加密失败,需要手动进行加密。 解密时映射对象类需要是字段加EncryptionField的类,否则无法识别到哪个字段是要进行解密的。 目前支持String类型的字段进行加解密

注解配置

在数据库表对应的类需要加密的字段,加上EncryptionField注解,该字段在进行保存或更新时自动对该字段进行加密,在读取的时候,进行解密

java
@Data
@Accessors(chain = true)
@TableName("pc_alipay_config")
public class AlipayConfig {

    /** 私钥 字段进行加密保存 */
    @EncryptionField
    private String privateKey;

    /** 应用公钥证书 */
    @BigField
    @EncryptionField
    private String appCert;

    /** 支付宝公钥证书 */
    @BigField
    @EncryptionField
    private String alipayCert;

    /** 支付宝CA根证书 */
    @BigField
    @EncryptionField
    private String alipayRootCert;
}

手动加解密

java
/**
 * 加密
 */
public Object encryptValue(Object fieldValue){
    if (fieldValue instanceof String){
        // fieldDecryptKey AES秘钥, 
        AES aes = SecureUtil.aes(fieldDecryptKey.getBytes(StandardCharsets.UTF_8));
        return aes.encryptBase64((String) fieldValue);
    } else {
        return fieldValue;
    }
}
/**
 * 解密
 */
public Object decryptValue(Object fieldValue){
    if (fieldValue instanceof String){
        AES aes = SecureUtil.aes(fieldDecryptKey.getBytes(StandardCharsets.UTF_8));
        return new String(aes.decrypt(Base64.decode((String)fieldValue)),StandardCharsets.UTF_8);
    }
    else {
        return fieldValue;
    }
}

相关配置

yaml
bootx.starter.data-perm:
  # 字段加密AES秘钥,需要符合AES格式
  field-decrypt-key: 秘钥

敏感数据脱敏

TIP

对应前端使用方法见 数据脱敏(Vue3)

返回值序列化方式要为Jackson,否则会不生效。目前支持String类型的字段进行脱敏 在要返回给前端对象类中的字段上,添加上SensitiveInfo注解,在数据返回前端时,字段根据设定的规则,对字段值进行脱敏

EncryptionField参数

  • value 敏感信息类型,参数为SensitiveType敏感信息脱敏类型枚举,具体类型如下
    • CHINESE_NAME 中文名,只显示第一个汉字,其他隐藏为2个星号,比如:李**
    • USER_ID 用户ID,userId 统一替换为 0L,
    • PASSWORD 密码,密码的全部字符都用*代替,比如:******
    • ID_CARD 身份证号,只显示前六位和后两位,如370112**********1X
    • FIXED_PHONE 座机号,显示前四位,后两位
    • MOBILE_PHONE 手机号,前三位,后4位,其他隐藏,比如135****2210
    • IP IP地址,只显示前两段ip,如192.168.*.*
    • ADDRESS 地址,只显示到地区(前6位),不显示详细地址,比如:北京市海淀区****
    • EMAIL 电子邮件地址,邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示,比如:d**@foxmail.com
    • BANK_CARD 中国大陆车牌,车牌中间用*代替,如鲁A8***0
    • BANK_CARD 银行卡,卡号脱敏 : 1101 **** **** **** 3256
    • CNAPS_CODE 公司开户银行联号,中间用*号代替
    • OTHER 其他,通过frontend属性来决定保留前面或后面几个字符正常显示
  • front 保留:前面的front位数;从1开始,敏感类型为其他时可用
  • end 保留:后面的end位数;从1开始,敏感类型为其他时可用

示例

java
@Data
@Accessors(chain = true)
@Schema(title = "用户信息")
public class UserInfoDto implements Serializable {
	@Schema(description= "名称")
    private String name;
    
    @Schema(description= "密码")
    @SensitiveInfo(SensitiveType.PASSWORD)
    private String password;

    @Schema(description= "手机号")
    @SensitiveInfo(SensitiveType.MOBILE_PHONE)
    private String phone;

    @Schema(description= "邮箱")
    @SensitiveInfo(SensitiveType.EMAIL)
    private String email;
}

数据范围权限

WARNING

一个用户只能分配一种数据权限,不支持拥有多种,如果用户未被分配数据权限,默认是SELF级别,只能查看自己的数据。在查询、更新、删除操作的时候可以应用数据范围权限, 如果是多表联查时,会以主表为准。如果未被MybatisPlus管理的表(有对应的数据实体类,并被MybatisPlus扫描到)和表中无权限字段或,会自动停用数据权限,防止出现SQL报错。

类型说明

  • SELF 只能查看自己的数据
  • USER_SCOPE 可以查看指定用户的数据
  • DEPT_SCOPE 可以查看指定部门的数据
  • DEPT_AND_USER_SCOPE 可以查看指定部门和指定用户的数据
  • ALL_SCOPE 可以查询全部数据
  • BELONG_DEPT 只能查看自己部门人员的数据
  • BELONG_DEPT_AND_SUB 可以查看自己部门及下级部门的数据

使用说明

在要进行用户数据范围权限控制的方法上添加 Permission 注解,该方法以及调用的子方法都将进行数据范围权限拦截,如果被嵌套的某些子方法不需要进行权限控制, 可以添加 NestedPermission 注解到方法或类上上来排除权限控制。

可以添加到类或者方法上,添加到类时对当前类所有方法生效,如果类和方法中都进行了添加,以方法上的为准。 放到数据实体类上时,如果dataScopeselectField值为false,将会在任何权限查询的时候停用权限控制,如果设置为true值无任何效果

@Permission

参数功能备注
dataScope数据范围权限默认为true
selectField查询字段权限默认为true

@NestedPermission

只会在@Permission嵌套的方法内生效,该方法需要被Spring代理到,否则不生效

参数功能备注
dataScope数据范围权限默认为false
selectField查询字段权限默认为false

示例

java

/**
 * 数据权限演示
 *
 * @author xxm
 * @date 2022/2/21
 */
@Slf4j
@Service
@Permission
@RequiredArgsConstructor
public class DataPermDemoService {

    private final DataPermDemoManager dataPermDemoManager;

    /**
     * 分页
     */
    @Permission
    public PageResult<DataPermDemo> page(PageParam pageParam) {
        return MpUtil.convert2PageResult(dataPermDemoManager.page(pageParam));
    }

    /**
     * 获取 单条
     */
    public DataPermDemo findById(Long id) {
        return dataPermDemoManager.findById(id).orElseThrow(DataNotExistException::new);
    }


    /**
     * 更新
     */
    public void update(DataPermDemo param) {
        DataPermDemo dataPermDemo = dataPermDemoManager.findById(param.getId()).orElseThrow(DataNotExistException::new);
        BeanUtil.copyProperties(param, dataPermDemo, CopyOptions.create().ignoreNullValue());
        dataPermDemoManager.updateById(dataPermDemo);
    }

    /**
     * 删除
     */
    public void delete(Long id) {
        dataPermDemoManager.findById(id).orElseThrow(DataNotExistException::new);
        dataPermDemoManager.deleteById(id);
    }

}

查询字段权限

TIP

通过结合@PermCode注解实现,将@PermCode注解加到数据库实体类或对应的字段上,在进行SQL查询时,会自动将没有权限的字段去掉,只查询拥有权限的字段。 启用和嵌套子方法使用方式同数据范围权限类似,需要在标注@Permission注解方法或子方法中才会生效。

使用说明

@PermCode注解可以放在数据实体类类上或字段上,放在字段上时,会对该字段启用查询字段权限,权限码可以配置多个,用户拥有任意一个就可, 放在类上时相当于所有字段都标注了该权限码。类和字段上同时都标注了该注解,相当于该字段拥有这两个注解的权限码合集。

示例

java
public class DataPermDemo extends MpBaseEntity {

    @PermCode("123")
    private String name;

    @PermCode("123")
    private String creatorName;

    @PermCode({"123","admin"})
    private String remark;
}
本文档内容版权属于济南易杯光年软件技术有限公司,保留所有权利