问题描述
我已经使用Block-kit UI创建了漫游器响应。 消息中包含一个文本消息和按钮元素。对于文本,我使用*粗体显示。因此,到目前为止,在松弛通道中以粗体显示的消息是可以的。但是当用户执行按钮操作时,请求验证失败。
这是代码: 控制器中的此方法可以接受来自Slack的消息并将消息发送回Slack
@PostMapping(path = "/slack")
@ResponseBody
public void handleslackrequest(
@RequestBody String requestBody) throws URISyntaxException
{
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
Map<Object,Object> mainMap = new HashMap<>();
mainMap.put("channel","DXXXXXXXXX");
mainMap.put("blocks","[{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"*Text message with bold characters.*\"}},{\"type\":\"section\",\"text\":\"This is a section block with a button.\"},\"accessory\":{\"type\":\"button\",\"text\":{\"type\":\"plain_text\",\"text\":\"Click Me\",\"emoji\":true},\"value\":\"click_me_123\"}}]");
URI uri = new URI("https://slack.com/api/chat.postMessage");
headers.add("Content-Type","application/json");
headers.set("Authorization","Bearer xoxb-11XXXXXXXX-13XXXXXXXXXX-Q2XXXXXXXXXXXXXXXXX");
httpentity<Object> restrequest = new httpentity<>(mainMap,headers);
ResponseEntity<String> result = restTemplate.exchange(uri,HttpMethod.POST,restrequest,String.class);
return;
}
如图像所示显示响应 https://i.stack.imgur.com/m0PCc.png
单击按钮时,以下方法将触发
@PostMapping(path = "/slackaction",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ResponseBody
public void handleSlackActionsConversationEvent(
@RequestHeader HttpHeaders headers,@modelattribute("payload") String requestPayload,@RequestBody String slackrequestActionMessage)
{
String slackrequestTimeStamp = headers.getFirst(slackrequestHeaders.X_SLACK_REQUEST_TIMESTAMP.getHeader());
String slackSignature = headers.getFirst(slackrequestHeaders.X_SLACK_SIGNATURE.getHeader());
boolean isValid = verifyIncomingslackrequest(slackrequestActionMessage,slackrequestTimeStamp,slackSignature);
return;
}
我正在使用以下代码来验证此[link]之后的请求 :https://api.slack.com/authentication/verifying-requests-from-slack
public boolean verifyIncomingslackrequest(String requestBody,String slackrequestTimeStamp,String slackSignature)
{
try
{
String signing_secret = "dXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
String[] split = slackSignature.split("=");
String versionNumber = split[0];
String requestKey = versionNumber + ":" + slackrequestTimeStamp + ":" + requestBody;
String siginingKey = encode(signing_secret,requestKey,versionNumber);
return siginingKey.equals(slackSignature);
}
catch (Exception e)
{
}
return false;
}
public String encode(String key,String data,String versionNumber) throws Exception
{
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(),"HmacSHA256");
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
sha256_HMAC.init(secret_key);
byte[] macBytes = sha256_HMAC.doFinal(data.getBytes());
StringBuilder hashValue = new StringBuilder(2 * macBytes.length);
for (byte macByte : macBytes)
{
hashValue.append(String.format("%02x",macByte & 0xff));
}
return versionNumber + "=" + hashValue.toString();
}
当Slack请求中的按钮操作和消息中包含*时,如果验证无效,验证就会失败。我是否错过了任何内容或方法是否不同?请对此我有任何想法。
解决方法
我遇到了这个确切的问题。尽管我使用的是php,但这可能对您有用。
$headers = getallheaders();
$raw_body = file_get_contents('php://input');
$x_slack_signature = $headers["X-Slack-Signature"];
$x_slack_timestamp = $headers["X-Slack-Request-Timestamp"];
$slack_signing_secret = "...";
请注意普通的连字符,而不是代码中的下划线。
/*
For computing the signature,I need the following:
1. $version
2. $x_slack_timestamp
3. $raw_body
All of them appended to each other with a colon (:)
*/
$signature_base_string = $version . ":" . $x_slack_timestamp . ":" . $raw_body;
$hash_signature = "v0=" . hash_hmac('sha256',$signature_base_string,$slack_signing_secret);
此后,我将它们进行比较,如果它们不匹配,则请求无效。