推送AKSK验证
功能介绍
当开启推送AK/SK验证,并设置推送AK和SK后,平台将在HTTP推送状态报告时增加签名时间戳(X-Sdk-Date)和用于消息鉴权的哈希码(Authorization)。
注意事项
修改AK/SK后生效时间大约5分钟,期间可能会导致状态报告/上行短信推送验证失败。可采用双AK/SK的方式,即同时支持两个AK/SK生效。通过Authorization请求头中的Access字段,可以判断当前请求所使用的有效SK(Secret Key)。
校验方法
需额外引入maven依赖,示例代码中使用了该依赖实现AK/SK签名。
以下代码示例中的version值,请根据实际的SDK版本号进行替换。具体的SDK版本号请参见SDK开发中心。
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.14.0</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency> <dependency> <!-- 使用时替换为实际路径--> <systemPath>${project.basedir}/libs/java-sdk-core-XXX.jar</systemPath> <groupId>com.huawei.apigateway</groupId> <artifactId>java-sdk-core</artifactId> <version>SDK版本号</version> <scope>system</scope> </dependency>
校验Authorization的java示例如下:
@RestController public class StatusReportController { private static final Pattern AUTHORIZATION_PATTERN_SHA256 = Pattern.compile( "SDK-HMAC-SHA256\\s+Access=([^,]+),\\s?SignedHeaders=([^,]+),\\s?Signature=(\\w+)"); private static Map<String, String> secretMap = new HashMap<>(); static { secretMap.put("exampleAk", "exampleSk*1231d881wd"); } static class Response { int returnCode; String returnCodeDesc; Response(int returnCode, String returnCodeDesc) { this.returnCode = returnCode; this.returnCodeDesc = returnCodeDesc; } public int getReturnCode() { return returnCode; } public String getReturnCodeDesc() { return returnCodeDesc; } } @PostMapping("/status") public ResponseEntity<Response> smsHwStatusReport(HttpServletRequest request) { if (!doAuth(request)) { // 验证失败,返回状态码 401 return ResponseEntity .status(HttpStatus.UNAUTHORIZED) // 设置 HTTP 状态为 401 .contentType(MediaType.APPLICATION_JSON) .body(new Response(401, "Unauthorized")); } // 正常处理状态报告 return ResponseEntity .status(HttpStatus.OK) .contentType(MediaType.APPLICATION_JSON) .body(new Response(0, "Success")); } public boolean doAuth(HttpServletRequest request) { try { if (StringUtils.isEmpty(request.getHeader("Authorization"))) { // 不包含 Authorization header return false; } Matcher match = AUTHORIZATION_PATTERN_SHA256.matcher(request.getHeader("Authorization")); if (!match.find()) { // Authorization 格式错误 return false; } String ak = match.group(1); // 获取access key String body = new String(IOUtils.toByteArray(request.getInputStream()), StandardCharsets.UTF_8); // // 获取消息体字符串 Request r = new Request(); r.setAppKey(ak); r.setSecret(secretMap.get(ak)); // 获取secret key r.setUrl(request.getRequestURI()); // 获取消息路径 r.setBody(body); r.setMethod(request.getMethod()); Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String headerName = headerNames.nextElement(); r.addHeader(headerName.toLowerCase(Locale.ROOT), request.getHeader(headerName)); } Signer signer = new Signer(); return signer.verify(r); } catch (Exception e) { return false; } } }