由于JSON的重新排列,SpringBoot中的HMAC验证失败

huwehgph  于 2023-10-16  发布在  Spring
关注(0)|答案(2)|浏览(114)

我正在尝试在springBoot中使用HMAC for REST API。我从Postman发送的请求是

{
    "name":"xyz",
    "description":"hello world",
    "phone":"123456",
    "id":"1"
}

它到达我的控制器,然后到达服务,在那里我有一个功能来验证HMAC。在控制器中,我将signature作为headerpayload传递到requestBody

@RestController
public class UserController {
    
    
    @Autowired
    UserInterface userInterface;
    
    @PostMapping(value = "/" ,consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public void createUser(@RequestBody User user, @RequestHeader Map<String, String> headers) {
        userInterface.hmacValidation(user, headers);
    }

}
@Service
public class UserService  implements UserInterface {
    public void hmacValidation(User requestBody, Map<String, String> header) {
        var headerSignature = header.get("signature");
        var payload = getRequestBodyAsString(requestBody);
        String result = Hashing.hmacSha256("12345".getBytes(StandardCharsets.UTF_8)).hashString(payload,StandardCharsets.UTF_8).toString();
        
    }
    
    private String getRequestBodyAsString(User requestBody) {

        var mapper = new ObjectMapper();
        String payload = null;
        try {
            mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
            payload = mapper.writeValueAsString(requestBody);
            } catch (JsonProcessingException e) {
        }
        return payload;
    }
}

在这里,从**getRequestBodyAsString(User requestbody)**函数中,我得到的输出是一个混洗/重新排列的JSON请求,它生成不同的签名,然后与客户端发送的签名不匹配。
从UserObject转换回来的有效负载:

{"name":"xyz","id":"1","description":"hello world","phone":"123456"}
public class User {
    
    private String name;
    private String id;
    private String description;
    private String phone;
}

客户端可以以任何顺序发送请求,但我必须验证签名,无论请求的顺序如何
还有其他方法可以验证HMAC吗?

1dkrff03

1dkrff031#

如果你想获取哈希值,你不应该进行哈希化。使用字符串或字节的请求。然后在得到散列后将其Map到pojo
例如:

public @ResponseBody String controllerMethod(HttpServletRequest httpReq,
        HttpServletResponse httpResponse) {

        BufferedReader bufferedReader;
        StringBuilder sb;
        sb = new StringBuilder();
        bufferedReader = httpReq.getReader();
        char[] charBuffer = new char[128];
        int bytesRead;
        while ((bytesRead = bufferedReader.read(charBuffer)) != -1) {
            sb.append(charBuffer, 0, bytesRead);
        }
        String reqBody = sb.toString();
 }

使用reqBody获取哈希值。

x6492ojm

x6492ojm2#

您需要使用原始有效载荷来验证HMAC,即UTF-8有效载荷的文本作为字节数组。必须使用收到的POST请求的整个正文,包括行尾。

相关问题