You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让自定义STS接收SAML令牌作为客户端凭据完成身份认证?

我之前做过类似的STS链式签发场景,刚好可以给你一套可行的方案,核心是把自定义STS配置成接收SAML 2.0传入令牌,验证后再签发自有令牌给下游WCF服务。下面是具体步骤和示例:

一、先搞定自定义STS的绑定配置:接受SAML 2.0 IssuedToken

自定义STS本质是一个WCF服务,需要用ws2007FederationHttpBinding来适配联邦身份场景,同时指定传入令牌类型为SAML 2.0。修改你的STS的web.config:

<system.serviceModel>
  <bindings>
    <ws2007FederationHttpBinding>
      <binding name="Saml2InboundBinding">
        <security mode="Message">
          <message establishSecurityContext="false">
            <!-- 指定传入令牌是SAML 2.0 -->
            <issuedTokenParameters tokenType="urn:oasis:names:tc:SAML:2.0:assertion">
              <!-- 配置信任的外部IdP元数据,自动获取证书和端点 -->
              <issuerMetadata address="https://your-external-idp/FederationMetadata/2007-06/FederationMetadata.xml" />
              <!-- 手动指定IdP的签名证书,确保验证可信 -->
              <issuerCertificate findValue="IdP_CERT_THUMBPRINT" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindByThumbprint" />
            </issuedTokenParameters>
          </message>
        </security>
      </binding>
    </ws2007FederationHttpBinding>
  </bindings>
  <services>
    <service name="YourNamespace.CustomSecurityTokenService">
      <!-- 端点使用上面配置的绑定,契约用WIF的IWSTrust13SyncContract -->
      <endpoint address="STS" binding="ws2007FederationHttpBinding" bindingConfiguration="Saml2InboundBinding" contract="Microsoft.IdentityModel.SecurityTokenService.IWSTrust13SyncContract" />
    </service>
  </services>
  <!-- WIF核心配置:信任IdP、验证证书 -->
  <microsoft.identityModel>
    <service>
      <audienceUris>
        <!-- 自定义STS的受众地址,确保SAML令牌的Audience匹配 -->
        <add value="https://your-custom-sts/STS" />
      </audienceUris>
      <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel">
        <trustedIssuers>
          <!-- 信任的外部IdP证书和名称 -->
          <add thumbprint="IdP_CERT_THUMBPRINT" name="https://your-external-idp/" />
        </trustedIssuers>
      </issuerNameRegistry>
      <certificateValidation certificateValidationMode="PeerOrChainTrust" />
    </service>
  </microsoft.identityModel>
</system.serviceModel>

二、自定义STS的代码逻辑:验证SAML令牌+生成自有令牌

你的自定义STS需要继承SecurityTokenService,重写两个核心方法:GetScope(确定依赖方信任范围)和GetOutputClaimsIdentity(处理传入声明并生成输出声明)。

示例代码:

using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.SecurityTokenService;
using System.Linq;

namespace YourNamespace
{
    public class CustomSecurityTokenService : SecurityTokenService
    {
        public CustomSecurityTokenService(SecurityTokenServiceConfiguration config) : base(config)
        {
        }

        protected override Scope GetScope(ClaimsPrincipal incomingPrincipal, RequestSecurityToken request)
        {
            // 验证依赖方(WCF服务)是否在信任列表里
            var relyingPartyUri = request.AppliesTo.Uri;
            if (!IsTrustedRelyingParty(relyingPartyUri))
            {
                throw new InvalidRequestException($"依赖方 {relyingPartyUri} 不受信任");
            }

            // 创建Scope:指定依赖方地址、STS的签名凭据
            var scope = new Scope(relyingPartyUri, Configuration.SigningCredentials);
            // 指定你要签发的自定义令牌类型,必须和下游WCF服务配置一致
            scope.TokenType = "urn:your-custom-sts:token:v1";
            // 可选:如果需要加密令牌,设置依赖方的加密证书
            // scope.EncryptingCredentials = new X509EncryptingCredentials(GetRelyingPartyCertificate(relyingPartyUri));

            return scope;
        }

        protected override ClaimsIdentity GetOutputClaimsIdentity(ClaimsPrincipal incomingPrincipal, RequestSecurityToken request, Scope scope)
        {
            // 从传入的SAML令牌中获取用户声明
            var incomingClaims = incomingPrincipal.Claims;

            // 1. 核心验证:确保关键声明存在,比如用户ID、令牌未过期等
            var userIdClaim = incomingClaims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
            if (userIdClaim == null)
            {
                throw new InvalidRequestException("SAML令牌缺少用户标识声明");
            }

            // 2. 声明转换:根据下游WCF服务的需求,过滤或转换声明
            var outputClaims = new List<Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, userIdClaim.Value),
                // 可以添加自定义声明,比如从SAML令牌提取角色,或者添加WCF需要的权限声明
                new Claim("http://your-custom-sts/claims/wcf-access", "Allowed"),
                // 保留SAML令牌中的其他必要声明,比如姓名、邮箱等
                incomingClaims.FirstOrDefault(c => c.Type == ClaimTypes.Name)
            }.Where(c => c != null).ToList();

            // 返回要嵌入到自定义STS令牌中的身份
            return new ClaimsIdentity(outputClaims, scope.TokenType);
        }

        // 辅助方法:验证依赖方是否可信
        private bool IsTrustedRelyingParty(Uri relyingPartyUri)
        {
            // 这里可以从配置或数据库中读取信任的依赖方列表
            return relyingPartyUri.AbsoluteUri == "https://your-wcf-service/";
        }
    }
}

三、下游WCF服务的配置:信任自定义STS的令牌

WCF服务需要配置成接受自定义STS签发的令牌,同样用ws2007FederationHttpBinding:

<system.serviceModel>
  <bindings>
    <ws2007FederationHttpBinding>
      <binding name="CustomSTSTokenBinding">
        <security mode="Message">
          <message establishSecurityContext="false">
            <issuedTokenParameters tokenType="urn:your-custom-sts:token:v1">
              <!-- 指定自定义STS的地址 -->
              <issuer address="https://your-custom-sts/STS" binding="ws2007FederationHttpBinding" />
              <!-- STS的元数据地址,自动获取配置 -->
              <issuerMetadata address="https://your-custom-sts/FederationMetadata/2007-06/FederationMetadata.xml" />
              <!-- 信任STS的签名证书 -->
              <issuerCertificate findValue="YOUR_STS_CERT_THUMBPRINT" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindByThumbprint" />
            </issuedTokenParameters>
          </message>
        </security>
      </binding>
    </ws2007FederationHttpBinding>
  </bindings>
  <services>
    <service name="YourWcfNamespace.WcfService">
      <endpoint address="" binding="ws2007FederationHttpBinding" bindingConfiguration="CustomSTSTokenBinding" contract="YourWcfNamespace.IWcfService" />
    </service>
  </services>
  <microsoft.identityModel>
    <service>
      <audienceUris>
        <add value="https://your-wcf-service/" />
      </audienceUris>
      <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel">
        <trustedIssuers>
          <add thumbprint="YOUR_STS_CERT_THUMBPRINT" name="https://your-custom-sts/" />
        </trustedIssuers>
      </issuerNameRegistry>
    </service>
  </microsoft.identityModel>
</system.serviceModel>

四、几个必须注意的点

  1. 证书信任链:所有参与方的证书(外部IdP、自定义STS、WCF服务)都要放到对应的信任存储(比如LocalMachine/TrustedPeople),否则令牌验证会失败。
  2. 令牌类型一致性:自定义STS签发的tokenType必须和WCF服务配置的完全一致,大小写都不能错。
  3. 声明验证要严格:在GetOutputClaimsIdentity里一定要验证SAML令牌的有效性,比如检查令牌过期时间、受众是否匹配自定义STS的地址,防止恶意令牌。
  4. 元数据维护:确保自定义STS和外部IdP都发布联邦元数据,这样配置可以自动更新,减少手动维护成本。

内容的提问来源于stack exchange,提问作者ANewGuyInTown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:21:11