5 changed files with 245 additions and 0 deletions
@ -0,0 +1,24 @@ |
|||||
|
package com.ruoyi.common.annotation; |
||||
|
|
||||
|
import java.lang.annotation.ElementType; |
||||
|
import java.lang.annotation.Retention; |
||||
|
import java.lang.annotation.RetentionPolicy; |
||||
|
import java.lang.annotation.Target; |
||||
|
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; |
||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
||||
|
import com.ruoyi.common.config.serializer.SensitiveJsonSerializer; |
||||
|
import com.ruoyi.common.enums.DesensitizedType; |
||||
|
|
||||
|
/** |
||||
|
* 数据脱敏注解 |
||||
|
* |
||||
|
* @author ruoyi |
||||
|
*/ |
||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||
|
@Target(ElementType.FIELD) |
||||
|
@JacksonAnnotationsInside |
||||
|
@JsonSerialize(using = SensitiveJsonSerializer.class) |
||||
|
public @interface Sensitive |
||||
|
{ |
||||
|
DesensitizedType desensitizedType(); |
||||
|
} |
@ -0,0 +1,67 @@ |
|||||
|
package com.ruoyi.common.config.serializer; |
||||
|
|
||||
|
import java.io.IOException; |
||||
|
import java.util.Objects; |
||||
|
import com.fasterxml.jackson.core.JsonGenerator; |
||||
|
import com.fasterxml.jackson.databind.BeanProperty; |
||||
|
import com.fasterxml.jackson.databind.JsonMappingException; |
||||
|
import com.fasterxml.jackson.databind.JsonSerializer; |
||||
|
import com.fasterxml.jackson.databind.SerializerProvider; |
||||
|
import com.fasterxml.jackson.databind.ser.ContextualSerializer; |
||||
|
import com.ruoyi.common.annotation.Sensitive; |
||||
|
import com.ruoyi.common.core.domain.model.LoginUser; |
||||
|
import com.ruoyi.common.enums.DesensitizedType; |
||||
|
import com.ruoyi.common.utils.SecurityUtils; |
||||
|
|
||||
|
/** |
||||
|
* 数据脱敏序列化过滤 |
||||
|
* |
||||
|
* @author ruoyi |
||||
|
*/ |
||||
|
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer |
||||
|
{ |
||||
|
private DesensitizedType desensitizedType; |
||||
|
|
||||
|
@Override |
||||
|
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException |
||||
|
{ |
||||
|
if (desensitization()) |
||||
|
{ |
||||
|
gen.writeString(desensitizedType.desensitizer().apply(value)); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
gen.writeString(value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) |
||||
|
throws JsonMappingException |
||||
|
{ |
||||
|
Sensitive annotation = property.getAnnotation(Sensitive.class); |
||||
|
if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) |
||||
|
{ |
||||
|
this.desensitizedType = annotation.desensitizedType(); |
||||
|
return this; |
||||
|
} |
||||
|
return prov.findValueSerializer(property.getType(), property); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 是否需要脱敏处理 |
||||
|
*/ |
||||
|
private boolean desensitization() |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
LoginUser securityUser = SecurityUtils.getLoginUser(); |
||||
|
// 管理员不脱敏
|
||||
|
return !securityUser.getUser().isAdmin(); |
||||
|
} |
||||
|
catch (Exception e) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,59 @@ |
|||||
|
package com.ruoyi.common.enums; |
||||
|
|
||||
|
import java.util.function.Function; |
||||
|
import com.ruoyi.common.utils.DesensitizedUtil; |
||||
|
|
||||
|
/** |
||||
|
* 脱敏类型 |
||||
|
* |
||||
|
* @author ruoyi |
||||
|
*/ |
||||
|
public enum DesensitizedType |
||||
|
{ |
||||
|
/** |
||||
|
* 姓名,第2位星号替换 |
||||
|
*/ |
||||
|
USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")), |
||||
|
|
||||
|
/** |
||||
|
* 密码,全部字符都用*代替 |
||||
|
*/ |
||||
|
PASSWORD(DesensitizedUtil::password), |
||||
|
|
||||
|
/** |
||||
|
* 身份证,中间10位星号替换 |
||||
|
*/ |
||||
|
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1** **** ****$2")), |
||||
|
|
||||
|
/** |
||||
|
* 手机号,中间4位星号替换 |
||||
|
*/ |
||||
|
PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")), |
||||
|
|
||||
|
/** |
||||
|
* 电子邮箱,仅显示第一个字母和@后面的地址显示,其他星号替换 |
||||
|
*/ |
||||
|
EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")), |
||||
|
|
||||
|
/** |
||||
|
* 银行卡号,保留最后4位,其他星号替换 |
||||
|
*/ |
||||
|
BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")), |
||||
|
|
||||
|
/** |
||||
|
* 车牌号码,包含普通车辆、新能源车辆 |
||||
|
*/ |
||||
|
CAR_LICENSE(DesensitizedUtil::carLicense); |
||||
|
|
||||
|
private final Function<String, String> desensitizer; |
||||
|
|
||||
|
DesensitizedType(Function<String, String> desensitizer) |
||||
|
{ |
||||
|
this.desensitizer = desensitizer; |
||||
|
} |
||||
|
|
||||
|
public Function<String, String> desensitizer() |
||||
|
{ |
||||
|
return desensitizer; |
||||
|
} |
||||
|
} |
@ -0,0 +1,49 @@ |
|||||
|
package com.ruoyi.common.utils; |
||||
|
|
||||
|
/** |
||||
|
* 脱敏工具类 |
||||
|
* |
||||
|
* @author ruoyi |
||||
|
*/ |
||||
|
public class DesensitizedUtil |
||||
|
{ |
||||
|
/** |
||||
|
* 密码的全部字符都用*代替,比如:****** |
||||
|
* |
||||
|
* @param password 密码 |
||||
|
* @return 脱敏后的密码 |
||||
|
*/ |
||||
|
public static String password(String password) |
||||
|
{ |
||||
|
if (StringUtils.isBlank(password)) |
||||
|
{ |
||||
|
return StringUtils.EMPTY; |
||||
|
} |
||||
|
return StringUtils.repeat('*', password.length()); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 车牌中间用*代替,如果是错误的车牌,不处理 |
||||
|
* |
||||
|
* @param carLicense 完整的车牌号 |
||||
|
* @return 脱敏后的车牌 |
||||
|
*/ |
||||
|
public static String carLicense(String carLicense) |
||||
|
{ |
||||
|
if (StringUtils.isBlank(carLicense)) |
||||
|
{ |
||||
|
return StringUtils.EMPTY; |
||||
|
} |
||||
|
// 普通车牌
|
||||
|
if (carLicense.length() == 7) |
||||
|
{ |
||||
|
carLicense = StringUtils.hide(carLicense, 3, 6); |
||||
|
} |
||||
|
else if (carLicense.length() == 8) |
||||
|
{ |
||||
|
// 新能源车牌
|
||||
|
carLicense = StringUtils.hide(carLicense, 3, 7); |
||||
|
} |
||||
|
return carLicense; |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue