一、使用python脚本获取蓝鲸智云token
python版本环境:3.11
python
# -*- coding: utf-8 -*-
import requests
def get_user_token(domain,user,password):
'''模拟用户登录,并返回 bk_token 和 bk_csrftoken'''
BK_PAAS_HOST = domain
USERNAME = user
PASSWORD = password
response = requests.get('{0}/login/?c_url=/'.format(BK_PAAS_HOST), verify=False)
bklogin_csrftoken = response.cookies.get('bklogin_csrftoken')
url = "{0}/login/?c_url=/".format(BK_PAAS_HOST)
headers = {
"Host": BK_PAAS_HOST.split("//")[1],
"Origin": BK_PAAS_HOST,
"Referer": "{0}/login/?c_url=/".format(BK_PAAS_HOST),
"Cookie": "bklogin_csrftoken={}".format(bklogin_csrftoken),
'Content-Type': 'application/x-www-form-urlencoded'
}
data = {
"csrfmiddlewaretoken": bklogin_csrftoken,
"username": USERNAME,
"password": PASSWORD,
}
req2 = requests.post(url=url,
data=data,
headers=headers,
verify=False,
allow_redirects=False)
bk_token = req2.cookies.get("bk_token")
bk_csrftoken = req2.cookies.get("bklogin_csrftoken")
return bk_token, bk_csrftoken
aaa,bbb = get_user_token('http://XXX.com','***','***')
print('bk_token',aaa)
print('bk_csrftoken',bbb)
二、需要将python脚本转化为java代码
注:我们注意到在python脚本中,为获取登录token需要对同一个登录地址做了两次请求:
在第一次get请求中,我们从响应体的cookie中获取到了bklogin_csrftoken参数的值。
在第二次进行post请求时,需要将bklogin_csrftoken的值放入到请求头的Cookie中,并且Post请求需要做ssl安全验证。
此时对同一个登录地址需要从get请求转换到post请求,这时会存在两个问题,
问题一:HTTP的响应码会返回302或者307,文章末尾会附上对这两个状态码的解释,设置请求禁止HTTP重定向,对应脚本中对应的 allow_redirects=False。
问题二:如果不设置SSL信任所有证书,就会存在证书验证不通过。但是不建议完全信任所有SSL证书,因为这会降低安全性。通常,应该使用合适的证书来验证SSL连接,对应脚本中verify=False。
因此我们需要在java代码中处理连接请求设置SSL认证和禁止重定向。
代码如下:
java
import okhttp3.*;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
public class OkHttpExample {
public static void main(String[] args) {
String domain = "http://***.com";
String url = "http://***.com/login/?c_url=/";
String bklogin_csrftoken = "";
String username = "***";
String password = "***";
String bk_token = "";
try {
// 创建信任所有证书的TrustManager
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
// 创建SSL上下文,信任所有证书
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// 设置SSL Socket Factory,信任所有证书
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
// 设置SSL Socket Factory
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
// 禁止HTTP重定向
builder.followRedirects(false);
OkHttpClient client = builder.build();
// 创建GET请求
Request request = new Request.Builder()
.url(url)
.build();
// 执行GET请求
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
// 获取响应中的所有Cookie
String cookies = response.header("set-cookie");
bklogin_csrftoken = extractCsrfToken(response.headers(), "bklogin_csrftoken=");
// 打印Cookie信息
System.out.println("Cookies: " + cookies);
} else {
System.out.println("Request was not successful. Response code: " + response.code());
}
// 创建POST请求
RequestBody requestBody = new FormBody.Builder()
.add("csrfmiddlewaretoken", bklogin_csrftoken)
.add("username", username)
.add("password", password)
.build();
Request request2 = new Request.Builder()
.url(url)
.addHeader("Cookie", "bklogin_csrftoken=" + bklogin_csrftoken)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.post(requestBody)
.build();
// 执行POST请求
Response response2 = client.newCall(request2).execute();
bk_token = extractCsrfToken(response2.headers(), "bk_token=");
System.out.println("bk_token =" + bk_token);
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
private static String extractCsrfToken(Headers headers, String nameValue) {
for (int i = 0; i < headers.size(); i++) {
String name = headers.name(i);
String value = headers.value(i);
if ("set-cookie".equalsIgnoreCase(name) && value.startsWith(nameValue)) {
String[] parts = value.split(";");
for (String part : parts) {
if (part.startsWith(nameValue)) {
return part.substring(nameValue.length());
}
}
}
}
return null;
}
}
打印结果:
Cookies: bklogin_csrftoken=UJ2W48tw******ftsmnSpScu*******AOcJIduYnGwt3a2oE8B; expires=Wed, 04 Sep 2024 07:29:08 GMT; Max-Age=31449600; Path=/; SameSite=Lax
bk_token =bkcrypt%24gAAAAABk-CpELzYtclVMOivK8obn3V*******NDqeOE6TxUiTA******MRx6pMrIbT7NTDoGyk-LuocQEyL8N5vN3pk7Vc%3D
请求蓝鲸智云接口时,请求头 需要带上Cookie参数,如下:
参数格式: Cookie:bk_token=****
302 与 303、307 的关系
区别
从实际效果看,302 允许各种各样的重定向,一般情况下都会实现为到 GET 的重定向,但是不能确保 POST 会重定向为 POST;而 303 只允许任意请求到 GET 的重定向;307 和 302 一样,除了不允许 POST 到 GET 的重定向。
那为什么有了 307 和 303 还需要 302呢?
302 在最初的定义中,内容和现在的 307 是一样的,不允许重定向方法的改写(从 POST 到 GET,由于 GET 不应该有 body,实际上 body 也被改了)。但是早期浏览器在实现的时候有的实现成 303 的效果,有的实现成 307 的效果。于是在之后的标准,302 在某些浏览器中错误的实现被写进规范,成为 303,而 302 原本的效果被复制了到了 307。在最近的一次标准修订中,302 标准被修改成不再强制需要维持原请求的方法。所以就产生了现在的 302、303 和 307 。