说明:以下安全配置目前仅适用于 HTTP 接口。
TronGrid 提供了项目级别的安全设置,以精细化控制 API Key 的使用。安全措施包括:
- 白名单 (Allowlists):限制允许的请求类型。
- JSON Web Token (JWT):启用基于 Token 的身份认证。
User-Agent AllowList
如果您要分发嵌入了 API Key 的应用程序(例如 Electron、iOS 或 Android 应用),并可配置自定义 User-Agent,我们建议将您应用程序的 User-Agent 字符串添加到 AllowList 中。配置完成后,任何来自 User-Agent 不匹配的平台的 API 请求都将被拒绝。
匹配规则:User-Agent AllowList 使用部分字符串匹配。如果请求头中的 User-Agent 包含 AllowList 中指定的字符串,则将其注册为匹配项。
示例:
Allowlist entry:com.example.dapp
Request:
curl -X POST \
https://api.trongrid.io/wallet/createtransaction \
-H 'User-Agent: com.example.dapp/v1.2.7 (Linux; Android 8.0; SM-G930V Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36' \
-H 'Content-Type: application/json' \
-H 'TRON-PRO-API-KEY: <your-trongrid-api-key>' \
-d '{
"to_address": "41e9d79cc47518930bc322d9bf7cddd260a0260a8d",
"owner_address": "41D1E7A6BC354106CB410E65FF8B181C600FF14292",
"amount": 1000
}'
Result: 请求被允许,所有其他 User-Agent 请求均被拒绝。Origin AllowList
为防止第三方在其网站上使用您的 API Key,您可以配置 Origin AllowList,将 API Key 的访问权限限制为特定的 HTTP Origin。
例如,若将应用程序部署到 mydapp.example.com,将此域名添加到您的 HTTP Origin AllowList 中,可确保任何不包含 Origin mydapp.example.com 的流量都将被拒绝。
HTTP Origin 匹配规则
HTTP 源点(Origin)匹配与 TLS 证书类似,支持通配符子域名模式。其中最左侧的子域名可以用特殊的通配符(*)替换,用以匹配任何此类子域。该通配符仅匹配单个子域名层级,且只能出现在条目的最左侧。
URL 协议(Scheme)是可选的,支持 http://、https:// 或任何您想要限制的特定协议。如果允许列表条目中包含协议,则请求的源(Origin)必须具有相同的协议。此外,包含特定协议的条目将限制请求只能来自该协议的 Origin。
示例:
假设您的 API 密钥已配置以下允许列表条目:https://*.example.com
- 成功匹配示例
当请求的 Origin 头部与规则完全吻合(协议一致且域名处于一级子域)时,请求将被允许。
# 示例请求
curl -X POST [https://api.trongrid.io/wallet/createtransaction](https://api.trongrid.io/wallet/createtransaction) \
-H 'TRON-PRO-API-KEY: <your-trongrid-api-key>' \
-H 'Origin: [https://myapp.example.com](https://myapp.example.com)' \
-H 'Content-Type: application/json' \
-d '{"to_address": "...", "owner_address": "...", "amount": 1000}'
| Origin Header | 结果 | 原因 |
|---|---|---|
https://myapp.example.com | 允许 | 协议 (https) 与一级子域名均匹配。 |
https://api.example.com | 允许 | 匹配通配符定义的一级子域。 |
- 拒绝匹配示例
以下请求将因违反匹配规则而被拦截:
| Origin Header | 结果 | 拒绝原因 |
|---|---|---|
http://myapp.example.com | 拒绝 | 协议不匹配: 条目要求必须使用 https。 |
https://example.com | 拒绝 | 层级不匹配: 通配符 * 必须占据一个子域位置,不包含根域名。 |
https://sub.myapp.example.com | 拒绝 | 深度不匹配: 通配符仅支持匹配单级子域名。 |
https://myapp.other-env.com | 拒绝 | 根域名不匹配: 必须以 example.com 结尾。 |
Contract Address AllowList
如果您的应用程序仅查询来自特定智能合约或地址的数据,请将这些地址添加到您的合约地址 AllowList 中。 一旦将地址添加到 AllowList,任何试图查询未包含在列表中地址的 API 请求都将被自动拒绝。
以下接口接受合约地址参数,并受此 AllowList 约束:
/v1/contracts/contract_address/events
/(event)|(events)/contract/contract_address
/(event)|(events)/contract/[a-zA-Z0-9]+/[a-zA-Z0-9]+
/(event)|(events)/contract/[a-zA-Z0-9]+/[a-zA-Z0-9]+/[a-zA-Z0-9]+
/walletsolidity/triggerconstantcontract
/wallet/triggersmartcontract
/wallet/triggerconstantcontract示例:
Allowlist entry: TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t
Request:
curl --request GET \
--url https://api.trongrid.io/v1/contracts/TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t/events \
--header 'TRON-PRO-API-KEY: <your-trongrid-api-key>'
Result: 请求通过。如果适用的请求方法中,传入的合约地址参数未包含在允许列表中,则该请求将被拦截。Requested API AllowList
您可以使用 API Key 将请求限制为特定的 TronGrid API 方法。如果此 AllowList 不为空,任何对未明确列出的方法的请求都将被拒绝。
示例:
Allowlist entry: walletsolidity_getTransactionById
Request:
curl --request GET \
--url https://api.trongrid.io/v1/accounts/TUD4YXYdj2t1gP5th3A7t97mx1AUmrrQRt \
--header 'TRON-PRO-API-KEY: <your-trongrid-api-key>' \
Result: 请求被拒绝,因为请求方法不是 walletsolidity_getTransactionById什么是 JWT?
JSON Web Token (JWT) 是一种开放标准 (RFC 7519),用于在应用程序环境之间以 JSON 对象的形式安全地传输信息。这些信息以声明 (Claims) 的形式存在,并通过数字签名确保其真实可靠。
是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。
在 TronGrid 中,JWT 用于在身份提供者和服务提供者之间传递经过身份验证的用户身份信息。该 Token 可用于验证请求并访问服务器资源。
如何使用 JWT
当启用 JWT 开关时,每个 API 请求都必须包含有效的 Token 信息以供 TronGrid 验证。未通过验证的请求将不会收到响应。
每个账户最多可以创建三个 JWT。创建 JWT 时需要您提供用户生成的公钥(目前使用 RS256 算法)。提交公钥后,系统将自动生成相应的 Key ID 和指纹 (Fingerprint)。
演示
以下步骤使用示例代码演示集成过程。
步骤 1:生成 RSA 密钥对
要在项目中使用 JWT,您必须首先生成一个公钥/私钥对。TronGrid 目前支持 RS256 算法。
注意:请确保您的私钥安全。切勿将其公开发布。
使用 OpenSSL 生成密钥:
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -outform PEM -pubout -out public.pem配置:输入一个易于识别的名称来标识密钥,并粘贴您的公钥文件 (public.pem) 中的文本内容。它应该是一个标准的 PEM 编码文件(例如由 OpenSSL 生成),如下所示:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvGek2v/H/TEzB+mnfbJ5
m7wgon0u/JjFQY3kYr6E0N4cRBQm8sy6ikNKi5x/1YxmhBqn6HvF9xD/p72eCBVe
RFh863pjWpF1C5yjOq3OEks00ayRP1ukATG8LtoUnWoPisXrh5/wVe4fHDPeNwe4
5RXOp6svO860o/ckAxt8yO/ZczqtN8cNA7unGawJ3cn8VeL+pa4a6f8DNfp32QUY
Y//HjPFvrTxcfJ4cM6E74L913P2CDuiSVVXMk0iyX/blh6M4h7dGAlcmHEHno9OW
5jrrAKobZZT1quc6qT43sTJviqc24Ndgas5jTOPhEV7bgkgQbTbtpgorHjUpqAIm
+wIDAQAB
-----END PUBLIC KEY-----步骤 2:生成 Token
方法 1:使用 Java 代码
- 添加依赖项:导入
jjwt包。
compile 'io.jsonwebtoken:jjwt-api:0.11.2'
runtime 'io.jsonwebtoken:jjwt-impl:0.11.2'
runtime 'io.jsonwebtoken:jjwt-jackson:0.11.2'- 调用
createSignedJwtRsa256生成 Token
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Header;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.spongycastle.util.encoders.Base64;
public class JwtTest {
private static PublicKey getRSAPublicKey(String inputKey)
throws NoSuchAlgorithmException, InvalidKeySpecException {
String rsaPublicKey = inputKey.replace("-----BEGIN PUBLIC KEY-----", "");
rsaPublicKey = rsaPublicKey.replace("-----END PUBLIC KEY-----", "");
rsaPublicKey = rsaPublicKey.replace("\n", "");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decode(rsaPublicKey));
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(keySpec);
}
public void createSignedJwtRsa256() {
/**
* {
* "alg": "RS256",
* "typ": "JWT",
* "kid": "bdbd8dabcb8d49f3ae9732c14c9940ea"
* }
*
* {
* "exp": 1617736153,
* "aud": "trongrid.io",
* }
* */
try {
PrivateKey privateKey = getRSAPrivateKey(privateKeyStr);
JwtBuilder builder = Jwts.builder()
.setHeaderParam("alg", "RS256")
.setHeaderParam("typ", "JWT")
.setHeaderParam("kid", "XXXXXXXXXXX") // your jwt key id
.claim("exp", 1617736153)
.claim("aud", "trongrid.io")
.signWith(privateKey, SignatureAlgorithm.RS256);
String token = builder.compact();
System.out.println(token);
} catch (Exception e) {
e.printStackTrace();
assert false;
}
}
}方法 2:使用在线工具 (jwt.io)
- 打开网站:jwt.io。
- 选择 RS256 算法。
- 输入 Header:提供
kid(JWT 的 ID)。将 JWT 添加到 API Key 后,即可在 API Key 配置中查看此 ID。
{ "alg": "RS256",
"typ": "JWT",
"kid": "XXXXXXX" // id of jwt
}- 输入 Payload:可选的
exp字段表示过期时间,可以留空。 (代码保持不变)
{
"exp": 1617736153,
"aud": "trongrid.io"
}- 验证签名:在 VERIFY SIGNATURE 一栏中,将公钥和私钥输入到相应的字段中。
- 获取 Token:在 ENCODED 一栏中将看到生成的 Token。
步骤 3:使用 Token
要对请求进行身份验证,在 HTTP 请求 Header 中,添加 Authorization 字段。
- 值格式:
Bearer <token>(注意:"Bearer" 和 Token 字符串之间必须有一个空格。)
示例:
curl -X POST \
https://api.trongrid.io/wallet/createtransaction \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer xxxxxx' \
-H 'TRON-PRO-API-KEY: <your-trongrid-api-key>' \
-d '{
"to_address": "41e9d79cc47518930bc322d9bf7cddd260a0260a8d",
"owner_address": "41D1E7A6BC354106CB410E65FF8B181C600FF14292",
"amount": 1000
}'import requests
url = "https://api.trongrid.io/wallet/createtransaction"
payload = "{\n \"to_address\": \"41e9d79cc47518930bc322d9bf7cddd260a0260a8d\",\n \"owner_address\": \"41D1E7A6BC354106CB410E65FF8B181C600FF14292\",\n \"amount\": 1000\n}"
headers = {
'Authorization': "Bearer xxxxxx",
'Content-Type': "application/json",
'TRON-PRO-API-KEY': "<your-trongrid-api-key>"
}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)var request = require("request");
var options = { method: 'POST',
url: 'https://api.trongrid.io/wallet/createtransaction',
headers: {
'Authorization': 'Bearer xxxxxx',
'TRON-PRO-API-KEY': '<your-trongrid-api-key>',
'Content-Type': 'application/json'
},
body: {
to_address: '41e9d79cc47518930bc322d9bf7cddd260a0260a8d',
owner_address: '41D1E7A6BC354106CB410E65FF8B181C600FF14292',
amount: 1000
},
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});配置约束
生成令牌时,请遵守以下规则:
- 固定标头类型:Header 中的
typ固定为"JWT"。 - 算法支持:目前仅支持 RS256(未来版本将增加对 ES256 的支持)。因此,
alg标头字段目前固定为"RS256"。 - 受众限制:Payload 中的
aud字段固定为"trongrid.io"。
示例:
//Header:
{
"alg": "RS256",
"typ": "JWT",
"kid": "bdbd8dabcb8d49f3ae9732c14c9940ea" // your jwt id
}
//Body
{
"exp": 1617736153,
"aud": "trongrid.io"
}