Note:
目前安全设置只对HTTP接口有效。
您可以使用如下几种特定于项目的安全设置来更好地控制API Key的使用:
- Allowlists - 限制允许的请求类型
- JWT - 身份验证
AllowList User Agent
如果您要分发嵌入了API key的产品,并且能够设置自定义User-Agent(例如,Electron应用,iOS或Android应用),则建议将已知的User-Agent添加到您的允许清单中。将User-Agent添加到允许列表后,任何来自其他平台的API请求都将被拒绝。
User-Agent允许列表利用部分字符串匹配。 如果请求的完整User-Agent中包含允许列表中列出的字符串,则将其注册为匹配项。
Allowlist entry:com.example.dapp
Request: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
Result: 请求被允许,所有其他用户代理请求均被拒绝
AllowList Origins
为了防止第三方在其网站上使用您的API Key,您可以列出允许使用API Key的HTTP来源。
如果要将应用程序部署到mydapp.example.com,则将mydapp.example.com添加到HTTP Origin允许列表中,以确保HTTP请求中不包含Origin:mydapp.example.com的所有流量都将被拒绝。
HTTP源点匹配与TLS证书类似,支持通配符子域模式,其中最左边的子域可以用特殊的 通配符替换以匹配任何此类子域。 匹配单个子域,并且只能显示为条目的最左侧部分。URL架构是可选的,可以是http:// 或 https:// 或您要限制的任何其他架构。 如果该架构包含在允许列表条目中,则源必须具有相同的架构。 此外,只有模式的条目将请求限制为该模式的origin。
Allowlist entry:https://*.example.com
Request's Origin Header:https://myapp.example.com
Result:由于架构和域名都匹配,因此允许上述请求。 来自与https://*.example.com不匹配的来源的任何请求都将被拒绝。 这可能包括http://myapp.example.com(不匹配的架构),https://myapp.somewhereelse.net(基础域不匹配)或https://subdomain.myapp.example.com(通配符可以仅匹配一级子域)。
AllowList Contract Addresses
如果您知道您的应用程序将仅查询来自特定智能合约或地址来源的数据,请将这些地址添加到您的合约地址允许列表。
将地址添加到允许列表后,所有查询地址不在允许列表中的API请求都会被拒绝。
以下接口采用合约地址参数:
/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: 25f66928-0b70-48cd-9ac6-da6f8247c663'
Result: 允许请求。 任何仅包含非允许的地址作为参数的请求方法都将被拒绝。
AllowList Requested Api
您可以使用您的API Key将请求限制为特定的调用方法。 如果列表不为空,则列表中未指定的任何方法调用都将被拒绝。
Allowlist entry: walletsolidity_getTransactionById
Request:
curl --request GET \
--url https://api.trongrid.io/v1/accounts/TUD4YXYdj2t1gP5th3A7t97mx1AUmrrQRt \
--header 'TRON_PRO_API_KEY: 25f66928-0b70-48cd-9ac6-da6f8247c663' \
Result: 请求被拒绝,因为请求方法不是walletsolidity_getTransactionById
JWT
什么是JWT
Json Web Tokens(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
如何使用JWT
如果开启了JWT开关,则每个请求都需要包含token信息,以让TronGrid进行验证,未通过验证的请求将不予响应,每个账号最多可以创建3个JWT,创建JWT时需要填入用户创建的公钥(现在支持的是RS256),填入公钥后会产生ID和Fingerprint。
示例
1.生成RSA密钥对
为了在项目中使用JWT,首先需要生成一个公钥/私钥对。Trongrid目前支持算法RS256。请保护好您的私钥!
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -outform PEM -pubout -out 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
方法一 使用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;
}
}
}
方法二 使用jwt网页
1 打开网址:https://jwt.io/
2 选择RSA256算法
3 输入header,其中kid为JWT的id,在为API Key添加JWT后,从API Key配置中查看
{ "alg": "RS256",
"typ": "JWT",
"kid": "XXXXXXX" // jwt的id
}
4 输入playload,exp为未过期时间,可不填写。
{
"exp": "1617736153",
"aud": "trongrid.io"
}
5 在VERIFY SIGNATURE 一栏中,分别输入公钥和私钥
6 在ENCODED一栏,则可以看到生成的token
3 使用token
在请求header中,增加Authorization 字段,其值为:Bearer XXXXXX。
其中XXXX为token,token和Bearer中间有一个空格。
4 注意事项
header中的"typ"固定为"JWT"。
目前只支持RS256,ES256会在后期版本中增加支持。所以在header中的alg字段目前固定为RS256。
playload中的"aud"固定为"trongrid.io"。
//Header:
{
"alg": "RS256",
"typ": "JWT",
"kid": "bdbd8dabcb8d49f3ae9732c14c9940ea" // your jwt id
}
//Body
{
"exp": 1617736153,
"aud": "trongrid.io"
}