7

API接口脱敏:如何安全地处理敏感数据?

 11 months ago
source link: https://www.51cto.com/article/768742.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

API接口脱敏:如何安全地处理敏感数据?

作者:Springboot实战案例锦集 2023-10-07 08:34:27
项目中开发的API接口,可能有些接口返回的字段信息不能以明文的形式传输,这时候我们该如何进行处理呢?

环境:SpringBoot2.6.12

API接口脱敏是一种保护敏感数据的重要方法。它涉及到在数据传输和存储过程中,将敏感数据替换为无意义或伪装的数据,以防止未经授权的访问和泄露。下面是一些关于如何安全地处理敏感数据的方法:

  1. 数据加密:使用加密算法对敏感数据进行加密,以确保即使数据在传输过程中被截获,也无法被解密。常见的加密算法包括对称加密算法(如AES)和非对称加密算法(如RSA)。
  2. 数据脱敏:使用数据脱敏技术,将敏感数据替换为无意义或伪装的数据。例如,将真实的手机号码替换为随机生成的虚假号码,或将真实的姓名替换为随机生成的虚假姓名。
  3. 访问控制:对API接口进行访问控制,只允许经过身份验证和授权的用户访问。使用身份验证令牌(如JWT)或OAuth等协议对用户进行身份验证和授权。
  4. 日志记录:对API接口的访问和使用情况进行详细的日志记录,以便在发生安全事件时能够迅速发现和应对。
  5. 数据传输安全:使用HTTPS协议进行数据传输,以确保数据传输过程中的安全性。
  6. 数据存储安全:将敏感数据存储在加密的数据库中,并使用访问控制列表(ACL)等技术对数据库进行访问控制。

项目中开发的API接口,可能有些接口返回的字段信息不能以明文的形式传输,这时候我们该如何进行处理呢?以下给出3中方式:

数据库层面处理

在SQL查询的时候进行处理,但这种效率不高,一般不会这样处理。如下:

SELECT
  CONCAT(LEFT( idNo, 6), '********', RIGHT (idNo, 4)) as idNo
FROM
  users where id = 7;

查询结果:

以掩码的方式处理部分数据以掩码的方式处理部分数据

数据加密处理

该种方式就是将你需要处理的字段完全通过对称加密或者HASH算法进行处理。在写入或者查询数据的时候对敏感数据进行加密/解密处理。示例如下:

import java.sql.*;  
  
public class JdbcSensitiveDataProcess {  
  public static void main(String[] args) {  
    try {  
      // 连接数据库  
      Connection conn = DataSourceUtils.getConnection() ;
      // 创建Statement对象  
      Statement stmt = conn.createStatement();  
      // 执行查询语句  
      ResultSet rs = stmt.executeQuery("SELECT id, name, encrypted_data FROM t_xxx");  
      // 遍历结果集  
      while (rs.next()) {  
        int id = rs.getInt("id");
        String name = rs.getString("name");
        String encryptedData = rs.getString("encrypted_data");
        // 对加密数据进行解密处理  
        String decryptedData = decryptData(encryptedData);
        // 输出解密后的数据  
        System.out.println("ID: " + id + ", Name: " + name + ", Decrypted Data: " + decryptedData);  
      }
    } catch (Exception e) {  
      e.printStackTrace();  
    } finally {
      // 关闭数据库相关资源
    }
  }  
  // 解密数据的方法,这里只是示例,实际需要根据具体的加密算法来实现  
  private static String decryptData(String encryptedData) {  
    // 解密逻辑...  
    // Cipher cipher = Cipher.getInsance(...) ;
    return decryptedData;  
  }  
}

JSON序列化时处理

API接口在生成JSON字符串的时候(序列化时)将敏感信息进行掩码处理或者加密处理,接下来将详细介绍第三种方式"JSON序列化时处理"。

JSON序列化处理脱敏

使用jackson时在对对象序列化时进行敏感字段的处理,为了简单我们通过自定义注解的方式来实现该功能。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
// 该注解必须,不然jackson不会识别该注解
@JacksonAnnotationsInside
// 指定我们需要序列化字段的实现
@JsonSerialize(using = SensitiveSerializer.class)
public @interface Sensitive {


  /**
   * 正则表达式
   * @return
   */
  String pattern() default "" ;


  /**
   * 正则表达式的第几个分组;该分组将被替换为掩码mask
   * @return
   */
  int group() default 0 ;


  /**
   * 掩码
   * @return
   */
  String mask() default "*" ;


  public interface Pattern {
    /**身份证*/
    String ID = "(\\w{5})(\\w+)(\\w{3})" ;
    /**电话*/
    String PHONE = "(\\w){3}(\\w+)(\\w{2})" ;
    /**私密*/
    String KEY = "(\\w+)" ;
  }
}

上面的注释类都有详细的说明,不再做过多的说明。

自定义序列化实现

public class SensitiveSerializer extends JsonSerializer<String> implements ContextualSerializer {


  private Sensitive sensitive ;


  @Override
  public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
    String val = value ;
    if (sensitive != null) {
      String pattern = sensitive.pattern() ;
      int groupIndex = sensitive.group() ;
      String mask = sensitive.mask() ;
      if (pattern.length() > 0) {
        Pattern pa = Pattern.compile(pattern) ;
        Matcher matcher = pa.matcher(value) ;
        if (matcher.matches()) {  
          String group = matcher.group(groupIndex) ;
          if (mask.length() > 0 && group.length() > 0) {
            val = val.replace(group, String.join("", Collections.nCopies(group.length(), mask))) ;
          }
        }
      }
    }
    gen.writeObject(val) ;
  }


  @Override
  public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
      throws JsonMappingException {
    sensitive = property.getAnnotation(Sensitive.class) ;
    return this ;
  }


}

该类实现了ContextualSerializer通过该类的回调方法能够用来读取当前字段上的注解信息。

public class Users {


  @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+10")
  private Date birthday ;
  private Integer age ;
  private String name ;
  // 在需要处理的字段上加入上面定义的注解,这里我们也可以自定义表达式
  @Sensitive(pattern = Sensitive.Pattern.ID)
  private String idNo
}

运行效果:

idNo按照指定的规则进行了掩码处理
idNo按照指定的规则进行了掩码处理

完毕!!!

责任编辑:武晓燕 来源: Spring全家桶实战案例源码

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK