引言:
通过宝塔API,可以完全控制宝塔Linux面板的所有功能,包括第三方插件应用功能,事实上,在用户登录面板 后使用的所有功能也是通过相同的接口对接的,这意味着,如果你熟悉使用浏览器调试器,就可以轻松对照宝塔Linux 面板的操作参数完成一个第三方的前端对接。
签名算法
api_sk = 接口密钥 (在面板设置页面-API接口中获取)
request_time = 当前请求时间的uinx时间戳 (php:time() / python:time.time())
request_token = md5(string(request_time) + md5(api_sk))
PHP 示例: $request_token=md5($request_time . ‘’ . md5($api_sk))
注意事项:
-
请统一使用POST方式请求API接口
-
为了确保请求效率,请保存cookie,并在每次请求时附上cookie
-
为了面板安全考虑,请务必添加IP白名单
-
所有响应内容统一为Json数据格式
DEMO:
BtApiHttp.java:
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;
public class BtApiHttp {
private String BT_KEY ; // 接口密钥
private String BT_PANEL ; // 面板地址
// 如果希望多台面板,可以在实例化对象时,将面板地址与密钥传入
public BtApiHttp(String btPanel, String btKey) {
if (btPanel != null) BT_PANEL = btPanel;
if (btKey != null) BT_KEY = btKey;
}
// 示例取面板日志
public String getLogs() {
// 拼接URL地址
String url = BT_PANEL + "/data?action=getData";
// 准备POST数据
Map<String, String> pData = getKeyData(); // 取签名
pData.put("table", "logs");
pData.put("limit", "10");
pData.put("tojs", "test");
// 请求面板接口
return httpPost(url, pData);
}
// 构造带有签名的关联数组
private Map<String, String> getKeyData() {
long nowTime = System.currentTimeMillis() / 1000;
String requestToken = getMD5Hash(nowTime + getMD5Hash(BT_KEY));
Map<String, String> pData = new HashMap<>();
pData.put("request_token", requestToken);
pData.put("request_time", String.valueOf(nowTime));
return pData;
}
// 发起HTTP POST请求
private String httpPost(String url, Map<String, String> data) {
try {
StringJoiner postData = new StringJoiner("&");
for (Map.Entry<String, String> entry : data.entrySet()) {
postData.add(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) + "=" + URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
}
URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(postData.toString());
writer.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
return response.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private String getMD5Hash(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hashInBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hashInBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
// 实例化对象
BtApiHttp api = new BtApiHttp("http://121.xx.xxx.64:xxxx", "xxxxxxxxxxxxxxxxxxxx");
// 获取面板日志
String logs = api.getLogs();
// 输出结果到控制台
System.out.println(logs);
}
}
BtApiHttps.java:
import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;
public class BtApiHttps {
private String BT_KEY; // 接口密钥
private String BT_PANEL; // 面板地址
// 如果希望多台面板,可以在实例化对象时,将面板地址与密钥传入
public BtApiHttps(String btPanel, String btKey) {
if (btPanel != null) BT_PANEL = btPanel;
if (btKey != null) BT_KEY = btKey;
}
// 示例取面板日志
public String getLogs() {
// 拼接URL地址
String url = BT_PANEL + "/data?action=getData";
//String url = BT_PANEL + "/system?action=GetSystemTotal";
// 准备POST数据
Map<String, String> pData = getKeyData(); // 取签名
pData.put("table", "logs");
pData.put("limit", "10");
pData.put("tojs", "test");
// 请求面板接口
return httpPost(url, pData);
}
// 构造带有签名的关联数组
private Map<String, String> getKeyData() {
long nowTime = System.currentTimeMillis() / 1000;
String requestToken = getMD5Hash(nowTime + getMD5Hash(BT_KEY));
Map<String, String> pData = new HashMap<>();
pData.put("request_token", requestToken);
pData.put("request_time", String.valueOf(nowTime));
return pData;
}
// 发起HTTPS POST请求
private String httpPost(String url, Map<String, String> data) {
try {
trustAllCertificates(); // 调用信任所有证书的方法
StringJoiner postData = new StringJoiner("&");
for (Map.Entry<String, String> entry : data.entrySet()) {
postData.add(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) + "=" + URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
}
HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(postData.toString());
writer.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
return response.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
// 信任所有证书的方法
private void trustAllCertificates() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
// 读取证书文件
String certPath = "D:/20201008072/baota_root.pem";
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(new FileInputStream(certPath));
// 创建 TrustManagerFactory,加载证书
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null, null);
keystore.setCertificateEntry("myserver", cert);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keystore);
// 创建 SSLContext 并初始化 TrustManager
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
// 实例化对象
BtApiHttps api = new BtApiHttps("https://121.43.xxx.xx:15220", "xxxxxxxxxxxxxxxxxxxx");
// 获取面板日志
String logs = api.getLogs();
// 输出结果到控制台
System.out.println(logs);
}
private String getMD5Hash(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hashInBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hashInBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
}
系统状态相关接口:https://www.bt.cn/data/api-doc.pdf
下面的DEMO只展示部分接口示例:
BtApiHttpsGetSystemTotal:
import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;
public class BtApiHttpsGetSystemTotal {
private String BT_KEY; // 接口密钥
private String BT_PANEL; // 面板地址
public BtApiHttpsGetSystemTotal(String btPanel, String btKey) {
if (btPanel != null) BT_PANEL = btPanel;
if (btKey != null) BT_KEY = btKey;
}
//获取日志信息
public String getLogs() {
String url = BT_PANEL + "/data?action=getData";
Map<String, String> pData = getKeyData();
pData.put("table", "logs");
pData.put("limit", "10");
pData.put("tojs", "test");
return httpPost(url, pData);
}
//获取系统基础统计
public String getSystemStats() {
String url = BT_PANEL + "/system?action=GetSystemTotal";
Map<String, String> pData = getKeyData();
return httpPost(url, pData);
}
//获取磁盘分区信息
public String GetDiskInfo(){
String url = BT_PANEL + "/system?action=GetDiskInfo";
Map<String, String> pData = getKeyData();
return httpPost(url, pData);
}
//获取实时状态信息(CPU、内存、网络、负载)
public String GetNetWork(){
String url = BT_PANEL + "/system?action=GetNetWork";
Map<String, String> pData = getKeyData();
return httpPost(url, pData);
}
//检查是否有安装任务
public String GetTaskCount(){
String url = BT_PANEL + "/ajax?action=GetTaskCount";
Map<String, String> pData = getKeyData();
return httpPost(url, pData);
}
//检查面板更新
public String UpdatePanel() {
String url = BT_PANEL + "/ajax?action=UpdatePanel";
Map<String, String> pData = getKeyData();
pData.put("check", "true"); //强制检查更新 [可选]
pData.put("force", "true"); //执行更新 [可选]
return httpPost(url, pData);
}
//获取网站列表
public String getDataTable() {
String url = BT_PANEL + "/data?action=getData&table=sites";
Map<String, String> pData = getKeyData();
pData.put("p", "1"); //当前分页 [可选]
pData.put("limit", "15"); //取回的数据行数 [必传]
pData.put("type", "1"); //分类标识, -1: 分部分类 0: 默认分类 [可选]
pData.put("order", "id desc"); //排序规则 使用 id 降序:id desc 使用名称升序:name desc [可选]
pData.put("tojs", "get_site_list"); //分页 JS 回调,若不传则构造 URI 分页连接 [可选]
pData.put("search", "www"); //搜索内容
return httpPost(url, pData);
}
//删除网站
public String DeleteSite() {
String url = BT_PANEL + "/site?action=DeleteSite";
Map<String, String> pData = getKeyData();
pData.put("id", "66"); //网站 ID [必传]
pData.put("webname", "w2_hao_com"); //网站名称 [必传]
pData.put("ftp", "1"); //是否删除关联 FTP ,如果不删除请不要传此参数[可选]
pData.put("database", "1"); //是否删除关联数据库,如果不删除请不要传此参数[可选]
pData.put("path", "1"); //是否删除网站根目录,如果不删除请不要传此参数[可选]
return httpPost(url, pData);
}
//停用网站
public String SiteStop() {
String url = BT_PANEL + "/site?action=SiteStop";
Map<String, String> pData = getKeyData();
pData.put("id", "66"); //网站 ID [必传]
pData.put("webname", "w2_hao_com"); //网站名称 [必传]
return httpPost(url, pData);
}
private Map<String, String> getKeyData() {
long nowTime = System.currentTimeMillis() / 1000;
String requestToken = getMD5Hash(nowTime + getMD5Hash(BT_KEY));
Map<String, String> pData = new HashMap<>();
pData.put("request_token", requestToken);
pData.put("request_time", String.valueOf(nowTime));
return pData;
}
private String httpPost(String url, Map<String, String> data) {
try {
trustAllCertificates();
StringJoiner postData = new StringJoiner("&");
for (Map.Entry<String, String> entry : data.entrySet()) {
postData.add(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) + "=" + URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
}
HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(postData.toString());
writer.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
return response.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private void trustAllCertificates() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
String certPath = "D:/20201008072/baota_root.pem";
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(new FileInputStream(certPath));
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null, null);
keystore.setCertificateEntry("myserver", cert);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keystore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
BtApiHttpsGetSystemTotal api = new BtApiHttpsGetSystemTotal("https://121.43.xxx.xx:15220", "xxxxxxxxxxxxxxxxxxxx");
String logs = api.getLogs();
String systemStats = api.getSystemStats();
String DiskInfo = api.GetDiskInfo();
String NetWork = api.GetNetWork();
String TaskCount = api.GetTaskCount();
String UpdatePanel = api.UpdatePanel();
String DataTable = api.getDataTable();
String DeleteSite = api.DeleteSite();
String SiteStop = api.SiteStop();
System.out.println("Logs: " + logs); //打印日志信息
System.out.println("System Stats: " + systemStats); //打印系统统计信息
System.out.println("GetDiskInfo: " + DiskInfo); //打印磁盘分区信息
System.out.println("GetNetWork: " + NetWork); //打印时状态信息(CPU、内存、网络、负载)
System.out.println("GetTaskCount: " + TaskCount); //检查是否有安装任务
System.out.println("UpdatePanel: " + UpdatePanel); //检查面板更新
System.out.println("GetDataTable: " + DataTable); //获取网站列表
System.out.println("DeleteSite: " + DeleteSite); //删除网站
System.out.println("SiteStop: " + SiteStop); //停用网站
} catch (Exception e) {
e.printStackTrace();
}
}
private String getMD5Hash(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hashInBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hashInBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
}