x-ca-key,x-ca-nonce,x-ca-signature与x-ca-signature-headers探索
curl 'https://bizapi.csdn.net/blog-console-api/v3/editor/getArticle?id=xxxxxxxxx&model_type=' \
-H 'accept: */*' \
-H 'accept-language: zh-CN,zh;q=0.9,en;q=0.8' \
-H 'cookie: ' \
-H 'origin: https://editor.csdn.net' \
-H 'referer: https://editor.csdn.net/' \
-H 'sec-ch-ua: "Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "Windows"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: same-site' \
-H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36' \
-H 'x-ca-key: 203803574' \
-H 'x-ca-nonce: d73db41b-e7bd-493b-8fe3-3a6995a422b3' \
-H 'x-ca-signature: rfYFgB84YDneWj2onHHmtJWeKUTsKC3EKsIurbvvR7E=' \
-H 'x-ca-signature-headers: x-ca-key,x-ca-nonce'
app.chunk.de89d64e.js
_ = function(t) {
var e = t.meth
, n = t.url
, r = t.appSecret
, a = t.accept
, o = t.date
, l = t.contentType
, d = t.params
, m = t.headers
, g = "";
d || -1 === n.indexOf("?") ? d || (d = {}) : (d = v(n),
n = n.split("?")[0]);
g += e + "\n",
g += a + "\n",
g += "\n",
g += l + "\n",
g += o + "\n";
var _ = h(m)// {x-ca-key: '203803574', x-ca-nonce: '924136a4-5eca-42ba-a675-34036764b896'}
, b = c()(s()(_)).sort() //['x-ca-key', 'x-ca-nonce']
, w = !0// treu
, y = !1// false
, x = void 0; //false
try {
// x-ca-key:203803574\nx-ca-nonce:924136a4-5eca-42ba-a675-34036764b896\n
for (var k, C = i()(b); !(w = (k = C.next()).done); w = !0) {
var L = k.value;
g += L + ":" + _[L] + "\n"
}
} catch (t) {
y = !0,
x = t
} finally {
try {
!w && C.return && C.return()
} finally {
if (y)
throw x
}
}
var S = /^(?=^.{3,255}$)(http(s)?:\/\/)?(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.csdn\.net)/
//n 'https://bizapi.csdn.net/blog-console-api/v3/mdeditor/saveArticle'
// T '/blog-console-api/v3/mdeditor/saveArticle'
, T = n.replace(S, "");
return g += f(T, d),
// g 'POST\n*/*\n\napplication/json\n\nx-ca-key:203803574\nx-ca-nonce:939abdaa-0bdd-4eba-a720-e8fc0b151621\n/blog-console-api/v3/mdeditor/saveArticle'
u()(g, r).toString(p.a)
}
入参t
{
"meth": "POST",
"url": "https://bizapi.csdn.net/blog-console-api/v3/mdeditor/saveArticle",
"accept": "*/*",
"date": "",
"contentType": "application/json",
"headers": {
"Content-Type": "application/json",
"Accept": "*/*",
"X-Ca-Key": "203803574",
"X-Ca-Nonce": "eff837eb-901e-403f-9ed3-d17d0227b16b"
},
"appSecret": "9znpamsyl2c7cdrr9sas0le9vbc3r6ba"
}
说明:
'POST\n*/*\n\napplication/json\n\nx-ca-key:203803574\nx-ca-nonce:eff837eb-901e-403f-9ed3-d17d0227b16b\n/blog-console-api/v3/mdeditor/saveArticle'
@Data
@Accessors(chain = true)
public class HmacSHA256Dto {
public String method;
public String accept;
public String contentType="";
public String date = "";
public String url;
public String appSecret = "9znpamsyl2c7cdrr9sas0le9vbc3r6ba";
public Map<String,Object> params;
public String xCaKey = "203803574";
public String xCaNonce;
}
get请求需要对参数排序,排序规则可能不对,欢迎指导,微信:lxwjy88,或评论区留言
@SneakyThrows
public static String getMessage(HmacSHA256Dto hmacSHA256Dto) {
URL url = new URL(hmacSHA256Dto.url);
String path = url.getPath();
StringBuffer sb = new StringBuffer();
sb.append(hmacSHA256Dto.method + "\n")
.append(hmacSHA256Dto.accept + "\n\n")
.append(hmacSHA256Dto.contentType + "\n")
.append(hmacSHA256Dto.date + "\n")
.append("x-ca-key:" + hmacSHA256Dto.xCaKey + "\n")
.append("x-ca-nonce:").append(hmacSHA256Dto.xCaNonce + "\n")
.append(path);
Map<String, Object> params = hmacSHA256Dto.params;
if (params != null) {
// 需要对参数排序,可能是默认排序也可能是其他排序,暂时没有用多参数测试过,临时用key排序,不知道对不对?欢迎留言指导,也可加微信:lxwjy88一起探讨
List<String> keys = new ArrayList<>(params.keySet());
Collections.sort(keys);
for (int i = 0; i < keys.size(); i++) {
String value = keys.get(i);
if (StringUtils.hasText(value)) {
if (i == 0) {
sb.append("?").append(value).append("=").append(params.get(value));
} else {
sb.append("&").append(value).append("=").append(params.get(value));
}
}
}
}
return sb.toString();
}
@SneakyThrows
public static String hmacSHA256(String secret, String message) {
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
hmacSha256.init(secret_key);
byte[] bytes = hmacSha256.doFinal(message.getBytes());
String s = Base64.getEncoder().encodeToString(bytes);
System.out.println(s);
return s;
}
public static void main(String[] args) {
String appSecret = "9znpamsyl2c7cdrr9sas0le9vbc3r6ba";
HmacSHA256Dto hmacSHA256Dto = new HmacSHA256Dto();
hmacSHA256Dto.setMethod("POST").setAccept("*/*").setContentType("application/json").setXCaNonce("939abdaa-0bdd-4eba-a720-e8fc0b151621").setUrl("https://bizapi.csdn.net/blog-console-api/v3/mdeditor/saveArticle\n");
String message = getMessage(hmacSHA256Dto);
hmacSHA256(appSecret, message);
}
至于x-ca-signature生成的对不对,可以用页面产生的X-Ca-Nonce作为随机串,看看自己计算出来的和页面生成的x-ca-signature一不一致,如果一致可以认为生成x-ca-signature的逻辑是对的