parent
86ca404dbf
commit
1140a6c333
@ -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