Microsoft 「Geneva」框架(後整合為 WIF/IdentityModel)提供構建自定義 STS 的完整編程模型。本文詳細演示如何實現主動/被動 STS、配置 WS-Trust 端點、處理聲明轉換、擴展令牌處理器,並對比 Geneva Server 的企業級特性。
public class IdentitySTS : SecurityTokenService {
public IdentitySTS(SecurityTokenServiceConfiguration config) : base(config) { }
protected override Scope GetScope(IClaimsPrincipal principal, RequestSecurityToken request) {
var scope = new Scope(request);
// 驗證 AppliesTo (RP 地址),返回加密憑證
scope.EncryptingCredentials = GetCredentialsForAppliesTo(request.AppliesTo);
// 簽名憑證 (STS 私鑰)
scope.SigningCredentials = new X509SigningCredentials(CertUtil.Get("CN=IPKey"));
return scope;
}
protected override IClaimsIdentity GetOutputClaimsIdentity(IClaimsPrincipal principal, RequestSecurityToken request, Scope scope) {
var id = new ClaimsIdentity();
id.Claims.Add(new Claim(ClaimTypes.Name, principal.Identity.Name));
id.Claims.Add(new Claim(ClaimTypes.Role, "Users"));
// 可擴展:查詢數據庫/AD 獲取角色、權限、Email 等聲明
return id;
}
}
public class IdentitySTSConfiguration : SecurityTokenServiceConfiguration {
public IdentitySTSConfiguration() : base("https://localhost:8010/sts") {
TokenIssuerName = "https://localhost:8010/sts";
SigningCredentials = new X509SigningCredentials(CertUtil.Get("CN=IPKey"));
SecurityTokenService = typeof(IdentitySTS);
// 程序化添加端點 (替代 config 文件)
TrustEndpoints.Add(new ServiceHostEndpointConfiguration("WSTrustFeb05", new WSHttpBinding(), typeof(IWSTrustFeb2005SyncContract)));
TrustEndpoints.Add(new ServiceHostEndpointConfiguration("WSTrust13", new WSHttpBinding(), typeof(IWSTrust13SyncContract)));
}
}
// 自託管
var host = new WSTrustServiceHost(new IdentitySTSConfiguration());
host.Open();
// IIS 託管 (.svc)
/* @ServiceHost Factory="Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceHostFactory" Service="STS.IdentitySTSConfiguration" */
<microsoft.identityModel>
<securityTokenHandlers>
<remove type="Microsoft.IdentityModel.Tokens.WindowsUserNameSecurityTokenHandler, ..." />
<add type="Microsoft.IdentityModel.Tokens.MembershipUserNameSecurityTokenHandler, ...">
<usernameSecurityTokenHandlerRequirement membershipProvider="CustomProviders.CustomMembershipProvider" />
</add>
</securityTokenHandlers>
<claimsAuthenticationManager type="STS.CustomClaimsAuthenticationManager, STS" />
</microsoft.identityModel>
自定義 UserNameSecurityTokenHandler 重寫 ValidateToken 實現非 Windows 認證(如數據庫驗證),返回 ClaimsIdentityCollection。
Default.aspx) 承載 FederatedPassiveTokenService 控件,處理登入/登出/令牌頒發/重定向。<!-- Default.aspx -->
<idfx:FederatedPassiveTokenService ID="FedPassive" runat="server" Service="STS.IdentityProviderSTSConfiguration, STS" />
<!-- web.config -->
<authentication mode="Forms" />
<authorization> <deny users="?" /> </authorization>
<microsoft.identityModel>
<federatedAuthentication enabled="true" />
</microsoft.identityModel>
<modules>
<add name="SessionAuthentication" type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, ..." />
</modules>
protected override Scope GetScope(...) {
var scope = base.GetScope(...);
scope.ReplyToAddress = scope.AppliesToAddress + "/default.aspx"; // RP 登陸頁
return scope;
}
用戶以任意憑證登入 → IP-STS 產生初始聲明 → 轉換為 RP 通用聲明 (Role/Action:Create/Read/Update/Delete) → 頒發令牌。

RP 僅請求最小聲明識別用戶 → 業務操作時 (如 DeleteCustomer) → RP 調用 RP-STS 申請上下文聲明 (Action:Delete) → 授權決策。

用戶域 B 登入 IP-STS → 獲取域 A RP-STS 信任的聲明 (RPClaim) → RP-STS 轉換為域 A 專用聲明 → RP 授權。

前提:IP-STS 與 RP-STS 建立信任,協商頒發聲明契約。
避免直接暴露敏感聲明 (如 Age) → RP 請求衍生聲明 (如 IsOver13) → STS 僅頒發衍生聲明,原始數據不出邊界。