如果要从 x509 证书/密钥生成JWT,对%SYS.X509Credentials的任何操作(包括读取)都需要 %Admin_Secure 资源上的 U。之所以需要 %Admin_Secure,是因为 %SYS.X509Credentials 是持久的,这样做是为了防止所有用户访问私钥。
如果 %Admin_Secure 资源在运行时不可用,可以使用以下变通方法。
在查看 JWT 生成代码时,我发现 JWT 代码仅利用 %SYS.X509Credentials 作为 PrivateKey、PrivateKeyPassword 和 Certificate 的运行时数据源。作为一种变通方法,您可以使用 X.509 接口的运行时非持久化实现,只公开这些属性。如果要使用互操作性,证书/PK 可以存储在凭证中,以便安全访问:
Class User.X509 Extends %RegisteredObject
{
Property PrivateKey As %VarString
Property PrivateKeyPassword As %String
Property Certificate As %VarString
Property HasPrivateKey As %Boolean [ InitialExpression = {$$$YES} ]
ClassMethod GetX509() As User.X509
{
set x509 = ..%New()
set x509.PrivateKey = ..Key()
set x509.Certificate = ..Cert()
quit x509
}
ClassMethod GetX509FromCredential(credential) As User.X509
{
set credentialObj = ##class(Ens.Config.Credentials).%OpenId(credential,,.sc)
throw:$$$ISERR(sc) ##class(%Exception.StatusException).ThrowIfInterrupt(sc)
set x509 = ..%New()
set x509.PrivateKey = credentialObj.Password
set x509.Certificate = credentialObj.Username
quit x509
}
ClassMethod Key()
{
q "-----BEGIN RSA PRIVATE KEY-----"_$C(13,10)
_"YOUR_TEST_KEY"_$C(13,10)
_"-----END RSA PRIVATE KEY-----"
}
ClassMethod Cert() As %VarString
{
q "-----BEGIN CERTIFICATE-----"_$C(13,10)
_"YOUR_TEST_CERT"_$C(13,10)
_"-----END CERTIFICATE-----"
}
}
您还可以通过以下方式生成 JWT:
ClassMethod JWT() As %Status
{
Set sc = $$$OK
Set x509 = ##class(User.X509).GetX509()
Set algorithm ="RS256"
Set header = {"alg": (algorithm), "typ": "JWT"}
Set claims= {"Key": "Value" }
#
Set sc = ##class(%Net.JSON.JWK).CreateX509(algorithm,x509,.privateJWK)
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
#
Set sc = ##class(%Net.JSON.JWKS).PutJWK(privateJWK,.privateJWKS)
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
Set sc = ##Class(%Net.JSON.JWT).Create(header,,claims,privateJWKS,,.pJWT)
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
Write pJWT
Return sc
}
或者,您也可以使用动态对象来跳过类的创建,在这种情况下,它将看起来像这样:
ClassMethod JWT(credential) As %Status
{
Set sc = $$$OK
Set credentialObj = ##class(Ens.Config.Credentials).%OpenId(credential,,.sc)
throw:$$$ISERR(sc) ##class(%Exception.StatusException).ThrowIfInterrupt(sc)
Set x509 = {
"HasPrivateKey": true,
"PrivateKey": (credentialObj.Password),
"PrivateKeyPassword":"",
"Certificate":(credentialObj.Username)
}
Set algorithm ="RS256"
Set header = {"alg": (algorithm), "typ": "JWT"}
Set claims= {"Key": "Value" }
#
Set sc = ##class(%Net.JSON.JWK).CreateX509(algorithm,x509,.privateJWK)
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
#
Set sc = ##class(%Net.JSON.JWKS).PutJWK(privateJWK,.privateJWKS)
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
Set sc = ##Class(%Net.JSON.JWT).Create(header,,claims,privateJWKS,,.pJWT)
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
Write pJWT
Return sc
}