阿里云日志服务介绍
日志服务(Log Service,简称SLS)是云原生观测与分析平台,为Log、Metric、Trace等数据提供大规模、低成本、实时的平台化服务。日志服务一站式提供数据采集、加工、查询与分析、可视化、告警、消费与投递等功能,全面提升您在研发、运维、运营、安全等场景的数字化能力。
数据加工服务是阿里云SLS推出的面向日志ETL处理的服务,主要解决数据加工过程中转换、过滤、分发、富化等场景。
本文档介绍如何使用DSL对接入到SLS中的JWT数据进行加解密处理,以便快速后续的日志分析等。
JWT是什么
JWT,全称是Json Web Token, 是JSON风格轻量级的授权和身份认证规范,可实现无状态、分布式的Web应用授权,它是分布式服务权限控制的标准解决方案。
SLS中原始数据会存在一些基于JSON Web Token (JWT)标准的数据,需要对其解码,所以有了jwt_encoding函数(编码)和jwt_decoding函数(解码)。这里主要介绍jwt_encoding和jwt_decoding函数。
SLS数据加工jwt处理函数
jwt_encoding
基于JSON Web Token (JWT)标准,对JSON数据进行编码
- 函数格式
jwt_encoding(payload, key, algorithm="HS256", headers=None)
- 参数说明
参数名称 |
参数类型 |
是否必填 |
说明 |
payload |
dict |
是 |
需要进行jwt编码的数据内容,JSON格式。JWT标准定义了7个字段,用户也可以自定义字段:
例如: { "iss": "user", "sub": "name", "aud": "user1", "some": "payload" } |
key |
String |
是 |
JWT加密密钥(与选定的加密算法相关):
|
algorithm |
String |
否 |
对令牌进行签名的算法,默认是HS256。 目前支持的算法有:HS256, |
headers |
dict |
否 |
JWT编码头信息,默认是 { "typ": "JWT", "alg": "HS256" } |
- 返回结果
返回编码后的字符串。
编码后的数据解释
包含三部分数据:
- Header:头部,通常头部有两部分信息:
- 声明类型type,这里是JWT(type=jwt)
- 加密算法,自定义(rs256/base64/hs256)
我们会对头部进行base64加密(可解密),得到第一部分数据
- Payload:载荷,就是有效数据,一般包含下面信息:
- 用户身份信息-userid,username(注意,这里因为采用base64加密,可解密,因此不要存放敏感信息)
- 注册声明:如token的签发时间,过期时间,签发人等
这部分也会采用base64加密,得到第二部分数据
- Signature:base64加密,签名,是整个数据的认证信息。一般根据前两步的数据,再加上服务的的密钥(secret,盐)(不要泄漏,最好周期性更换),通过加密算法生成。用于验证整个数据完整和可靠性。
头部(header)
头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以 被表示成一个JSON对象。如:
{"typ":"JWT", "alg":"HS256"}
这就是头部的明文内容,第一部分说明他是一个jwt,第二部分则指出签名算法用的是HS256算法。
然后将这个头部进行BASE64编码,编码后形成头部:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
载荷(payload)
载荷就是存放有效信息的地方,有效信息包含三个部分:
(1)标准中注册的声明(建议但不强制使用)
- iss: jwt签发者
- sub: jwt所面向的用户
- aud: 接收jwt的一方
- exp: jwt的过期时间,这个过期时间必须要大于签发时间
- nbf: 定义在什么时间之前,该jwt都是不可用的.
- iat: jwt的签发时间
- jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
(2)公共的声明
公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息. 但不建议添加敏感信息,因为该部分在客户端可解密.
(3)私有的声明
私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64 是对称解密的,意味着该部分信息可以归类为明文信息。
如:{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
上面就是一个简单的载荷的明文,接下来使用base64加密:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
签证(signature)
jwt的第三部分是一个签证信息,这个签证信息由三部分组成:
- header (base64后的)
- payload (base64后的)
- secret
这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第 三部分。
总之,jwt_encoding编码后的数据实际上就是一个字符串,有三部分组成:Header.payload.signature,每部分都是通过base64加密而成的。
jwt_decoding
基于JSON Web Token (JWT)标准,将数据解码为原始JSON
- 函数格式
jwt_decoding(jwt_payload,key="",algorithms=None,options=None,audience=None,issuer=None,leeway=0)
- 参数说明
参数名称 |
参数类型 |
是否必填 |
说明 |
jwt_payload |
String |
是 |
需要被解码的jwt。 |
key |
String |
是 |
JWT加密密钥(与选定的加密算法相关):
|
algorithms |
list |
是 |
对令牌进行签名的算法,例如 HS256。 |
options |
dict |
否 |
扩展解码和验证选项。
例如: {"require": ["aud"], "verify_aud": True} |
audience |
String/list |
否 |
用于检查aud的值 ,编码时候设置了'aud'参数,且 options扩展项中设置了"require": ["aud"] 或者"verify_aud": True时,解码就必须设置该参数 。 |
issuer |
String |
否 |
用于检查iss的值 ,编码时候设置了'iss'参数,且 options扩展项中设置了"require": ["iss"] 或者"verify_iss": True时,解码就必须设置该参数 。 |
leeway |
float |
否 |
到期检查的时间间隔(以秒为单位)。 |
应用场景
场景一 使用对称加密算法HS256(HMAC)
原始日志:
data: {"some": "payload"}
加工规则:
e_set("jwt_token", jwt_encoding(v("data"),"secret", algorithm="HS256"))
e_set("data_decoded", jwt_decoding(v("jwt_token"), "secret", algorithms="HS256"))
加工结果:
data:{"some": "payload"}
data_decoded:{"some": "payload"}
jwt_token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzb21lIjoicGF5bG9hZCJ9.Joh1R2dYzkRvDkqv3sygm5YyK8Gi4ShZqbhK2gxcs2U
场景二 使用非对称算法RS256(RSA)
原始日志:
data: {"some": "payload"}
加工规则:
e_set("jwt_token", jwt_encoding(v("data"),"-----BEGIN RSA PRIVATE KEY-----\nMIICYQIBAAKBgQC1iaUr5cgShCn0127+w14XN297q/IviaewIeIJsKTZF1hBPsLn\nNIPsnqtQ9DFbjIyqyZvdmQFDJCSLpXaVc648yepnFDKbOfs3r+K4Crnpo2SuZmNV\nNDVEi4pECXlBz810zJY1wqVArM7qGAyCcRLBprwXB6wfEhk3CAP3c29+pwIDAQAB\nAoGAARo65I9arbIbxx7fz7BEDAQMK0YaDGvbltg91S07cw4PPSYybNEG1BMKm01A\nV3v9BrR+u9PIDC5WAnsYwiODqEoSyk8OwO1E2kWA6+MNclYYfVjaJeiRJ5PzCud/\niUObonptRzxuTng+u1oGuX7QwUhwGJdXVBUAtJFYwXR2qVECRQC5S+6vdFESRLSX\n7yBZVM6+49lZcdehMv0HwT17UseLvWcjeSbiogvv02HbYilrW9ZydKsixAWP5w/U\nS3L34CS811VcDQI9APrOiL7c1xg5fX8wAWv2d+e+MfZoB3ohb8671W3pmp3JVnjY\ntzhoYNNQmnmRQQWf7n3J63MQz4sYYNn0gwJEE/pl37Dw1MFnn0H/AOKt79LtKkGl\n+BFhSqbBFDzWmvBu4Fo9oQ3Lr63gzSCGSrb6JhkCIptz5hIJmOARozwdeebVozkC\nPQDwOqVmU3c/P8nB6oRiGditw1Jt1yTaSW6jkOyUc73iRngqFkIgqHGd1kWwDX4/\nWfoAyEhalY6Fh5s1COsCRQCy4b3hnQws5zz/gmGNnoyxn9N+A09ySaFtn2WkUlrR\nZ6DwoJz+n6EgjLY8z6ZQyv342iobO5zKkZHFvO9QYGqk7y8lJA==\n-----END RSA PRIVATE KEY-----\n", algorithm="RS256"))
e_set("data_decoded", jwt_decoding(v("jwt_token"), "-----BEGIN RSA PUBLIC KEY-----\nMIGJAoGBALWJpSvlyBKEKfTXbv7DXhc3b3ur8i+Jp7Ah4gmwpNkXWEE+wuc0g+ye\nq1D0MVuMjKrJm92ZAUMkJIuldpVzrjzJ6mcUMps5+zev4rgKuemjZK5mY1U0NUSL\nikQJeUHPzXTMljXCpUCszuoYDIJxEsGmvBcHrB8SGTcIA/dzb36nAgMBAAE=\n-----END RSA PUBLIC KEY-----\n", algorithms="RS256"))
加工结果:
data:{"some": "payload"}
data_decoded:{"some": "payload"}
jwt_token:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzb21lIjoicGF5bG9hZCJ9.Ewwls5YPuJCmAR3XR2tcptOLrH83wVCzmUaUpGMzMLcPknRrIvbDmFGlNlQha-PMx0jsxt3t1oxpz7P3z3SR9o4qyWusAb99UG_Jn8oP8W0a5GKSy4UEJB0xgpVvJl5F2JaIPeUSHpV0VeS2WAsGSBBSAaOMkrc-8uie-H4J9M0
场景三 自定义headers内容
原始日志:
data: {"some": "payload"}
加工规则:
e_set("jwt_token", jwt_encoding(v("data"),"secret", algorithm="HS256", headers={"kid": "230498151c214b788dd97f22b85410a5"}))
e_set("data_decoded", jwt_decoding(v("jwt_token"), "secret", algorithms="HS256"))
加工结果:
data:{"some": "payload"}
data_decoded:{"some": "payload"}
jwt_token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjIzMDQ5ODE1MWMyMTRiNzg4ZGQ5N2YyMmI4NTQxMGE1In0.eyJzb21lIjoicGF5bG9hZCJ9.gdQ884yjlnLnIrYjfQaClE6rJC2x8v2OP2s_eXOLhZA
场景四 未经验证用户声明
原始日志:
data: {"some": "payload"}
加工规则:
e_set("jwt_token", jwt_encoding(v("data"),"secret", algorithm="HS256"))
e_set("data_decoded", jwt_decoding(v("jwt_token"), options={"verify_signature": False}))
加工结果:
data:{"some": "payload"}
data_decoded:{"some": "payload"}
jwt_token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzb21lIjoicGF5bG9hZCJ9.Joh1R2dYzkRvDkqv3sygm5YyK8Gi4ShZqbhK2gxcs2U
场景五 原始数据字段为含有用户声明,验证iat
原始日志:
data: {"some": "payload", "iss": [1, 2], "sub": "name", "nbf": 123,"iat": "22"}
加工规则:
e_set("jwt_token", jwt_encoding(v("data"),"secret"))
e_set("data_decoded", jwt_decoding(v("jwt_token"), "secret",algorithms="HS256",options={"require": ["iat"],"verify_iat": True}))
加工结果:
data:{"some": "payload", "iss": [1, 2], "sub": "name", "nbf": 123,"iat": "22"}
data_decoded:{"some": "payload", "iss": [1, 2], "sub": "name", "nbf": 123, "iat": "22"}
jwt_token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzb21lIjoicGF5bG9hZCIsImlzcyI6WzEsMl0sInN1YiI6Im5hbWUiLCJuYmYiOjEyMywiaWF0IjoiMjIifQ.2j5Q4Oag1oBBaQYV5GH2bJWrk4f-OKqsGTPvE9q-syQ
场景六 原始数据字段为含有用户声明,验证iss
原始数据:
data:{"some": "payload", "iss": "urn:foo"}
加工规则:
e_set("jwt_token", jwt_encoding(v("data"),"secret"))
e_set("data_decoded", jwt_decoding(v("jwt_token"), "secret",issuer="urn:foo", algorithms=["HS256"]))
加工结果:
data:{"some": "payload", "iss": "urn:foo"}
data_decoded:{"some": "payload", "iss": "urn:foo"}
jwt_token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzb21lIjoicGF5bG9hZCIsImlzcyI6InVybjpmb28ifQ.KUsdL-cGUBYkqRJTCt1IDxI_YTN4-1CwcZdWkPk1vP8
场景七 原始数据字段为含有用户声明,验证aud
原始日志:
data: {"some": "payload", "aud": ["urn:foo", "urn:bar"]}
加工规则:
e_set("jwt_token", jwt_encoding(v("data"),"secret"))
e_set("data_decoded", jwt_decoding(v("jwt_token"), "secret",audience="urn:foo", algorithms=["HS256"]))
加工结果:
data:{"some": "payload", "aud": ["urn:foo", "urn:bar"]}
data_decoded:{"some": "payload", "aud": ["urn:foo", "urn:bar"]}
jwt_token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzb21lIjoicGF5bG9hZCIsImF1ZCI6WyJ1cm46Zm9vIiwidXJuOmJhciJdfQ.Xhlfx9T5kTyehePsxKpcD81EB5tZ8sCoMHHP6kSE1v8
其他参考
1、SLS相关说明: https://yuque.antfin-inc.com/slssh/ops/sheke3#Cg08I