API 安全性:使用散列来维护客户端和服务器之间的数据完整性 [英] API Security : Using Hashing to Maintain data Integrity Between Client and Server

查看:22
本文介绍了API 安全性:使用散列来维护客户端和服务器之间的数据完整性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Android 客户端,可将 JSON 数据发送到我的 Spring Boot 应用程序服务器.

I have an Android client that sends JSON data to my spring boot application server.

另外,为了在通信期间保持一定级别的数据完整性,我需要对原始有效负载进行哈希处理,然后将其与原始 JSON 数据一起设置为传出有效负载.

In other to maintain a certain level of data integrity during communication I require that the original payload be hashed and then set into the outgoing payload along with the original JSON data.

这就是我的意思(Android 客户端)

This is what I mean (Android Client)

signUpUserRequest = new SignUpUserRequest(
                        lastName.getText().toString(),
                        Long.valueOf(phoneNumber.getText().toString().trim()),
                        emailAddress.getText().toString(),
                        Config.getAndroidId(this),
                        Type.INDIVIDUAL.toString(),
                        firstName.getText().toString(),
                        Config.ToBase64Encode(confirmPassword.getText().toString())
                );
                signUpUserRequest.setHash(Config.HashString(signUpUserRequest.toDataString().trim()));

下面是 SignUpUserRequest Pojo(为简洁起见,删除了 Setter 和 getter)

Below is the the SignUpUserRequest Pojo (Setters and getters removed for brevity)

public class SignUpUserRequest {

private String firstName;

private String lastName;

private long phoneNumber;

private String type;

private String email;

private String password;

private String phoneId;

private String hash;

public SignUpUserRequest(String lastName, Long phoneNumber, String email, String phoneId, String type, String firstName, String password) {
    this.lastName = lastName;
    this.phoneNumber = phoneNumber;
    this.email = email;
    this.phoneId = phoneId;
    this.type = type;
    this.firstName = firstName;
    this.password = password;
}
.... setters and getters removed ....

public String toDataString() {
    return "SignUpUserRequest{" + "firstName=" + firstName + ", lastName=" + lastName + ", phoneNumber=" + phoneNumber + ", type=" + type + ", email=" + email + ", password=" + password + ", phoneId=" + phoneId + '}';
}

@Override
public String toString() {
    return "SignUpUserRequest{" + "firstName=" + firstName + ", lastName=" + lastName + ", phoneNumber=" + phoneNumber + ", type=" + type + ", email=" + email + ", password=" + password + ", phoneId=" + phoneId + ", hash=" + hash + '}';
}

我遇到的问题是,当我将 JSON 发送到我的 Spring Boot 应用程序,然后对请求数据进行完整性检查时,服务器端生成的哈希值始终与客户端生成的哈希值不同.

The problem I have is when I send the JSON over to my spring boot application and then carry out an integrity check on the request data, the hash generated on the server side is always different from the hash generated on the client side.

服务端代码(Spring Boot 应用)

Server Side Code (Spring boot Application)

 public ResponseEntity getSignupSessionJWTToken(@RequestBody SignUpUserRequest request) {
    Response response = new Response();
    String hashString = Config.HashString(request.toDataString().trim());

   if (hashString.equals(request.getHash())) {
   ...... do anything here .....
   }else{
   ..... integrity exception ....
   }

所以我的问题是这是正确的方法吗?我是否在做一些根本错误的事情,我如何才能最好地实现客户端和服务器之间的数据完整性.

So My question is this the right approach? Am I doing something fundamentally wrong and how best can I achieve data integrity between my client and server.

hashString (Android) 的实现

Implementation of the hashString (Android)

public static String HashString(String text) {
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(text.trim().getBytes("UTF-8"));
        Log.i("CONFIG", "HASHING TEXT = " + ToBase64Encode(hash));
        return ToBase64Encode(hash);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(Config.class.getName()).log(Level.SEVERE, null, ex);
        return "";
    } catch (UnsupportedEncodingException e) {
        Logger.getLogger(Config.class.getName()).log(Level.SEVERE, null, e);
        return "";
    }
}

public static String ToBase64Encode(byte[] originalInput) {
    return new String(Base64.encodeToString(originalInput, Base64.DEFAULT));
}

hashString (SpringBoot) 的实现

Implementation of the hashString (SpringBoot)

public static String HashString(String text) {
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
        // System.out.println("Compare this = " + ToBase64Encode(hash));
        return Base64.getEncoder().encodeToString(hash);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(RiceHelper.class.getName()).log(Level.SEVERE, null, ex);
        return "";
    }
}

推荐答案

客户端的 base64 输出不是 Url 安全的,因为它在编码时使用 Base64.DEFAULT 标志.编码结果中的+"字符在服务器端接收时被转换为-"字符.因此比较失败.为了验证这一点,您可以从客户端发送的编码 base64 字符串和在服务器端接收的字符串.

The base64 output at your client side is not Url safe since it uses Base64.DEFAULT flag while encoding. The "+" character in the encoded result is being converted to a "-" character when received at the server side. Hence the comparison is failing. To verify this you can the encoded base64 string you are sending from your client and the string you receive at the server side.

为了确保 Url 安全,请使用 -

To make it Url safe, use -

byte[] encoded = Base64.encode(
strBytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);

这篇关于API 安全性:使用散列来维护客户端和服务器之间的数据完整性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆