什么是 JWT?
JWT (JSON Web Token,JSON 网络令牌)是一种开放标准(RFC 7519),它提供了一种轻量级、紧凑、自足的方法,用于在双方之间安全地传输信息。它常用于网络应用程序中的身份验证、授权和信息交换。
JWT 通常由三部分组成:
1.JOSE(JSON Object Signing and Encryption,JSON 对象签名和加密)标头
2.有效载荷
3.签名
这些部分以 Base64Url 格式编码,并用点(.)分隔。
JWT 的结构
标题
{ "alg": "HS256", "typ": "JWT"}
有效载荷
{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}
签名:
签名用于验证 JWT 的发件人是否为其本人,并确保信息未被篡改。
创建签名
1. base64 编码报头和有效载荷。
2.使用秘钥(对于对称算法,如 HMAC)或私钥(对于非对称算法,如 RSA)应用签名算法(如 HMAC SHA256 或 RSA)。
3.对结果进行 Base64Url 编码,以获得签名。
JWT 样本。查看JWT 内容
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
在 IRIS 中创建 JWT
注:2024 年以前,%OAuth2.JWT类用于在 IRIS 中生成 JWT。现在,%Net.JSON.JWT类是创建 JWT 的主要类,我将在示例代码中使用该类。
JWK 概述
JWK 表示加密密钥,特别用于签署和验证 JWT。通过 JWK,您可以用一种标准化格式来表示公钥(用于验证)和私钥(用于签名),以便在系统间轻松交换。JWKS 拥有多个 JWK
JWT 工作流程
1.以%DynamicObject 的形式构建头信息,并根据需要添加自定义头信息
2.直接以 %DynamicObject 构建正文/注释
3.调用 %Net.JSON.JWT 类的Create 方法
Set sc = ##Class(%Net.JSON.JWT).Create(header, , claims, jwks, , .JWT)
创建 JWK
Set sc = ##Class(%Net.JSON.JWK).Create("HS256","1212ASD!@#!#@$@#@$$#SDFDGD#%+_)(*@$SFFS",.privateJWK,.publicJWK)
这将返回私钥
{"kty":"oct","k":"MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT","alg":"HS256"}
一些重要的 JWK 属性
"kty":"oct"- 表示 对称 算法
"kty":"RSA" / "kty":"EC"- 表示 非对称 算法
创建 JWK 后,就可以将其添加到JWKS 中。
让我们在 IRIS 中创建 JWKS
Set sc = ##class(%Net.JSON.JWKS).PutJWK(jwk,.JWKS)
此方法返回 JWKS
在 IRIS 中生成 JWT
您可以在 IRIS 中创建对称或非对称密钥 JWT。%Net.JSON.JWK 类主要用于生成 JWT。 在调用该方法之前,请确保在生成JWT 时为对称加密和非对称加密创建并发送了JWKS 。
对称加密
对称算法使用共享密钥,发送方和接收方都使用相同的密钥来签署和验证 JWT。这些算法,如 HMAC(HS256、HS512、HS384),会为 JWT 有效负载生成散列(签名)。不建议高安全性系统采用这种方法,因为签名和验证都暴露在外,会带来潜在的安全风险。
%Net.JSON.JWK 类中的 Create 方法用于生成 JWK。该方法接收两个输入参数,并返回两个输出参数:
1.算法 - 用于创建 JWK 的算法。
secert - 用于签署和验证 JWT 的密钥。
privateJWK - 创建的私人 JSON 网络密钥。
publicJWK - 创建的公共 JSON Web 密钥。
For symmetric key algorithms - you'll get privateJWK
for Asymmetric key algorithms- You'll get privateJWK and publicJWK
ClassMethod SymmetricKeyJWT()
{
Set secret = "1212ASD!@#!#@$@#@$#SDFDGD#%+_)(*@$SFFS"
设置算法="HS256"
Set header = {"algorithm": (algorithm), "typ":"JWT", "x-c": "te"}
Set claims= {"sub":"1234567890", "name":"John Doe", "iat":1516239022 }
#; 创建 JWK
Set sc = ##class(%Net.JSON.JWK).Create(algorithm,secret,.privateJWK)
如果 $$ISERR(sc) {
写入 $SYSTEM.OBJ.DisplayError(sc)
}
ZWrite privateJWK
#; 创建 JWKS
Set sc = ##class(%Net.JSON.JWKS).PutJWK(privateJWK,.privateJWKS)
如果 $$ISERR(sc) {
写入 $SYSTEM.OBJ.DisplayError(sc)
}
ZWrite privateJWKS
Set sc = ##Class(%Net.JSON.JWT).Create(header,,claims,privateJWKS,,.pJWT)
如果 $$ISERR(sc) {
写入 $SYSTEM.OBJ.DisplayError(sc)
}
写入 pJWT
退出
}
输出
LEARNING>d ##class(Learning.JWT.NetJWT).SymmetricKeyJWT()
privateJWK={"kty":"oct","k":"MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT","alg":"HS256"} ; <DYNAMIC OBJECT>
privateJWKS="{""keys"":[{""kty"":""oct"",""k"":""MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT"",""alg"":""HS256""}]}"
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsIngtYyI6InRlIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.PcCs_I8AVy5HsLu-s6kQYWaGvuwqwPAElIad11NpM_E
非对称加密
非对称加密是指使用一对密钥:一个密钥用于签署令牌(私钥),另一个密钥用于验证令牌(公钥)。这与对称加密不同
私钥:该密钥用于签署 JWT。它是保密的,绝对不能暴露。
公钥:此密钥用于验证 JWT 的真实性。它可以安全地共享和分发,因为它不能用来签署新的标记。
您可以通过%SYS.X509Credentials 生成带有私钥/证书的 JWT 非对称加密。
ClassMethod AsymmetricWithx509()
{
Set x509 = ##class(%SYS.X509Credentials).%OpenId("myprivateTest1")
设置算法="RS256"
Set header = {"algorithm": (algorithm), "typ":"JWS", "x-c": "te"}
设置索赔= {"sub":"1234567890", "name":"John Doe", "iat":1516239022 }
#; 创建 JWK
Set sc = ##class(%Net.JSON.JWK).CreateX509(algorithm,x509,.privateJWK,.publicJWK)
ZWrite privateJWK,publicJWK
如果 $$ISERR(sc) {
写入 $SYSTEM.OBJ.DisplayError(sc)
}
#; 创建 JWKS
Set sc = ##class(%Net.JSON.JWKS).PutJWK(privateJWK,.privateJWKS)
ZWrite privateJWKS
如果 $$ISERR(sc) {
写入 $SYSTEM.OBJ.DisplayError(sc)
}
sigJWKS - 私有
Set sc = ##Class(%Net.JSON.JWT).Create(header,,claims,privateJWKS,,.pJWT)
如果 $$ISERR(sc) {
写入 $SYSTEM.OBJ.DisplayError(sc)
}
写入 pJWT
退出
}
网络应用中的 JWT
从2023 版开始,IRIS 默认为网络应用程序内置 JWT 创建功能。在设置网络应用程序时,确保启用 JWT 身份验证
我已添加了有关配置的简要说明
1.在网络应用程序中启用JWT 身份验证
2.如果还没有,创建一个 REST 类
3.包含默认端点资源"/login"。使用基本身份验证调用 REST API,有效载荷为 {"user":"_SYSTEM","password":"SYS"}。
4.4. 响应将是一个 JSON 文件,其中包含 "access_token"、"refresh_token "和其他相关详细信息。
5.5. 使用 "access_token "进行授权。