我所做的是:我创建了自己的响应消息版本,其中包含创建 GenericXmlSecurityToken 所需的位。这通常是从 WSTrustChannel 返回的,所以这似乎是正确的做法。值得庆幸的是,包装 JWT 的 GenericXmlSecurityToken 的大多数参数都是空的。我只需要序列化令牌,使用服务中 JWTSecurityTokenHandler 上的 WriteToken 序列化,以及 validFrom 和 validTo 值。
客户端代码:
XmlElement element = document.CreateElement("wsse", "BinarySecurityToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
element.SetAttribute("ValueType", "urn:ietf:params:oauth:token-type:jwt");
element.SetAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
UTF8Encoding encoding = new UTF8Encoding();
element.InnerText = Convert.ToBase64String(encoding.GetBytes(jwtToken));
GenericXmlSecurityToken token = new GenericXmlSecurityToken(
element,
null,
validFrom,
validTo,
null,
null,
null);
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.IssuedTokenType = "urn:ietf:params:oauth:token-type:jwt";
var factory2 = new ChannelFactory<IService1>(binding, new EndpointAddress("https://localhost:44300/Service1.svc"));
factory2.Credentials.SupportInteractive = false;
factory2.Credentials.UseIdentityConfiguration = true;
var proxy = factory2.CreateChannelWithIssuedToken(token);
var info = proxy.DoWork();
web.config 的相关位:
绑定:
<ws2007FederationHttpBinding>
<binding>
<security mode="TransportWithMessageCredential">
<message issuedKeyType="BearerKey" establishSecurityContext="false" issuedTokenType="urn:ietf:params:oauth:token-type:jwt"/>
</security>
</binding>
</ws2007FederationHttpBinding>
身份模型部分:
<system.identityModel>
<identityConfiguration>
<audienceUris>
<add value="--audienceUri--"/>
</audienceUris>
<securityTokenHandlers>
<add type="--namespace--.CustomJWTSecurityTokenHandler, --my dll--" />
<securityTokenHandlerConfiguration>
<certificateValidation certificateValidationMode="PeerTrust"/>
</securityTokenHandlerConfiguration>
</securityTokenHandlers>
<issuerNameRegistry>
<trustedIssuers>
<add name="--issuer--" thumbprint="--thumbprint--"/>
</trustedIssuers>
</issuerNameRegistry>
</identityConfiguration>
</system.identityModel>
还有来自这个问题的 CustomJWTSecurityTokenHandler (我的场景只需要 validIssuer 部分):How to configure MIcrosoft JWT with symmetric key?
我还没有看到在其他地方使用的issuedTokenType 属性,但我发现它对于让我的代码正常工作是必不可少的。没有它,我收到此错误:“MessageSecurityException:找不到'Microsoft.IdentityModel.Tokens.JWT.JWTSecurityToken'令牌类型的令牌身份验证器。根据当前的安全设置,无法接受该类型的令牌。”
作为一种解决方案,这可能有点矫枉过正,但我认为它最大限度地减少了自定义代码的数量,并将其集中在我觉得更舒服的地方。
感谢 user2338856 和 minimumprivilege 让我中途到达!