cas和saml
随着组织寻求最大程度地重用现有IT资产,基于面向服务的体系结构(SOA)的应用程序变得越来越普遍。 通常通过根据作为服务公开的应用程序逻辑构造松散耦合的复合应用程序来实现这种重用。 确保每个服务组件都知道原始服务请求者的身份,对于纠正基于SOA的许多应用程序的操作至关重要。 没有身份传播,授权决策和审核数据通常就毫无意义。
需要Web服务安全性标准,以确保异构环境中的互操作性。 WS-Security标准及其依赖项 (例如WS-Trust和WS-SecurityPolicy)是该领域中的重要标准。
使用安全断言标记语言(SAML)安全令牌类型的身份传播方案很常见。 SAML安全令牌提供的身份表示为:
- 标准(通过OASIS)
- 平台无关
- 广泛实施
- XML格式
- 能够包含自定义扩展属性
这些功能使SAML安全令牌成为表示Web服务(尤其是跨越组织或功能边界的Web服务)中的身份的理想候选者。 在本文中,将使用Tivoli Federated Identity Manager(TFIM)来启用使用Microsoft ASP.NET应用程序服务器和Web服务增强功能(WSE)构建的应用程序,而ASP.NET本身不具备此功能。
本引言部分的其余部分简要介绍了本文介绍的关键技术。
Microsoft Web服务增强
Microsoft Web服务增强功能是Microsoft .NET框架受支持的扩展,可以在Web服务领域提供高级功能。 .NET框架提供了包括基本安全性在内的某些Web服务功能,而WSE包含Microsoft对诸如WS-Security和WS-Trust之类的Web服务中的关键行业标准的实现。 WSE提供与Microsoft Visual Studio开发环境的集成,并且与较新的Microsoft Windows Communications Foundation(WCF)有线兼容。
WSE通过策略声明保护Web服务的安全。 提供了许多内置的断言(交钥匙断言)。 交钥匙声明的示例包括:
- usernameOverTransportSecurity-使用UsernameToken进行身份验证,但不对消息进行加密或签名
- usernameForCertificateSecurity-使用UsernameToken对客户端进行身份验证,但是使用X.509证书提供服务器身份验证。 消息级安全性已执行
- kerberosSecurity-客户端和服务器均使用Kerberos令牌进行身份验证,并执行消息级安全性
通常使用策略配置文件以声明方式配置策略,该文件包含对包含策略声明类的程序集的引用以及每个声明的任何配置。 在应用程序的配置文件(即Web.config或app.config)中引用了策略配置文件,并且应用程序本身指定了要使用的策略配置的名称。 清单2包含此类策略配置文件的示例。
清单2. WSE 3.0策略文件的示例
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="usernameOverTransportSecurity" \
type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion, \
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, \
PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader" \
type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion, \
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, \
PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="ServicePolicy">
<usernameOverTransportSecurity />
<requireActionHeader />
</policy>
</policies>
SAML
SAML是OASIS组织的安全服务工作的通用名称。 SAML规范的最新版本是2.0。 以前的版本是1.0和1.1。 最初是针对安全性断言标记语言的,该规范已经代表了更多的内容。 SAML规范描述:
- 断言 ,指定身份的表示方式。
- 协议 ,表示旨在实现单个目标的一系列XML消息。
- 绑定 ,描述如何通过较低级别的协议(例如HTTP)传输协议消息。
- 配置文件 ,它结合了许多绑定来描述用例的解决方案。
在SOA身份传播上下文中,SAML声明最为重要。 SAML断言的解剖图如图1所示。
图1. SAML断言的剖析
如上所述,SAML断言是XML文档。 清单1中显示了一个示例SAML 2.0声明。
清单1. SAML 2.0断言示例
<saml:Assertion ID="Assertion-uuid4cb533c2-0114-158f-a641-a2d10441b2a0"
IssueInstant="2007-08-09T22:18:37Z"
Version="2.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:wsse="http://oasis-open.org/wss/2004/01/oasis-wss-wssecurity-secext-1.0.xsd"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wsa="http://www.w3.org/2005/08/addressing">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
Acme
</saml:Issuer>
<ds:Signature Id="uuid4cb538fe-0114-17bf-9ca4-a2d10441b2a0">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#Assertion-uuid4cb533c2-0114-158f-a641-a2d10441b2a0">
<ds:Transforms>
<ds:Transform
Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<xc14n:InclusiveNamespaces PrefixList="ds saml"
xmlns:xc14n="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>1m+7Q3VXjgP7D0OjQIob+CP8QyI=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>...</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified">
testuser
</saml:NameID>
</saml:Subject>
<saml:Conditions NotBefore="2007-08-09T22:13:37Z" NotOnOrAfter="2007-08-09T22:23:37Z">
<saml:AudienceRestriction>
<saml:Audience>https://fw.acme.com/services/CreditCheck</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2007-08-09T22:18:37Z">
<saml:AuthnContext>
<saml:AuthnContextClassRef>
urn:oasis:names:tc:SAML:2.0:ac:classes:Password
</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="FirstName">
<saml:AttributeValue xsi:type="xs:string"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
John
</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="Surname">
<saml:AttributeValue xsi:type="xs:string"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
Citizen
</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
Tivoli联合身份管理器
Tivoli Federated Identity Manager(TFIM)是IBM解决方案,用于在面向服务的体系结构(SOA)中传播身份。 在SOA中启用身份传播的TFIM的核心组件是安全令牌服务(STS)。 STS支持WS-Trust规范(请参阅参考资料 ),该规范为SOA基础结构提供了一种基于标准的机制,以供访问SOA基础结构以访问身份服务以验证,转换和发布表示身份的安全性令牌。 SOA组件和TFIM STS之间的交互如图2所示。
图2.在SOA中使用TFIM STS
在TFIM STS中,可以指定不同的身份传播配置。 这些配置称为模块链 。 根据AppliesTo,Issuer和TokenType参数的值,将STS的传入请求与TFIM中的信任模块链进行匹配。 这样,相同的逻辑STS实例可以支持各种不同的身份要求。
TFIM STS可以使用许多不同的安全令牌类型进行操作,包括:
- SAML 1.0
- SAML 1.1
- SAML 2.0
- 用户名
- 的Kerberos
- X.509证书
- 轻量级第三方认证(LTPA)
- 树液
此外,如果需要,可以为自定义安全令牌开发新的安全令牌模块。
Tivoli Access Manager与Microsoft .NET的集成
Tivoli Access Manager与Microsoft .NET(AMNET)的集成是IBM支持站点提供的受支持的解决方案。 在Microsoft .NET环境中,AMNET提供:
- 访问Tivoli Access Manager(TAM)授权API
- 访问TAM管理API
- TAM评估基于角色的访问控制决策
- 用于ASP.NET环境的Web单点登录解决方案
在WSE中使用SAML安全令牌的模式
在本节中,显示了将SAML安全令牌与Microsoft WSE一起使用的概念性体系结构。 这些是常规模式,不特定于SAML安全令牌或Microsoft WSE的使用。 它们旨在说明解决SOA中身份传播难题的可重复方法,并为下一部分描述原型提供动力。
服务请求者模式
服务请求者模式认识到服务消费者需要“按预期发送”服务。 此模式以身份令牌表示服务组件中已认证的身份,并使用STS将已认证的身份转换为适合在服务请求中发送的身份令牌(图3)。 此模式最常见的用途是准备一个身份令牌,该令牌包含接收服务组件的域中的身份,并以服务请求的接收者期望的格式包含该身份,无论它是中介(例如企业服务总线还是企业服务总线)服务实现本身。
例如,ASP.NET应用程序可以充当WebSphere®ESB上发布的应用程序的Web服务客户端。 WebSphere ESB可能期望SAML断言形式的身份作为“标准Intranet令牌”。 将要求ASP.NET应用程序以SAML断言的形式提供服务请求者的身份。
图3.服务请求者身份传播模式
服务提供商模式
服务提供者模式如图4所示。传入身份令牌被发送到STS以进行验证并映射到本地身份。 在期望接收服务组件接受它本身无法支持的身份令牌的情况下使用此模式。 这样做的动机可能是采用了企业范围的令牌标准,或者服务组件的验证功能不足以满足特定SOA环境的要求。
例如,充当Web服务的ASP.NET应用程序可以接收来自不同业务部门或组织的请求。 在这种情况下,可以选择开放的,平台无关的SAML断言令牌类型,以实现最大的灵活性和互操作性。
图4.服务提供商身份传播模式
解决方案设计
该解决方案的关键是利用在Microsoft WSE中实现自定义安全策略声明的功能。 在实现自定义断言时,必须考虑并可选地实现四个方案:
- 客户发送请求
- 服务收到请求
- 服务发送回复
- 客户收到回应
此解决方案可自定义来自客户端的出站请求和服务接收到的请求的行为。 关键组件如图5所示。
图5. TFIM安全策略声明
TFIM信托客户
客户端输出过滤器和服务输入过滤器都将需要通过WS-Trust协议与TFIM STS通信。 这是在建立与TFIM信任服务的连接的信任客户端的帮助下完成的,并处理WS-Trust令牌验证和交换的所有方面。 在正常运行时操作期间,此信任客户端的使用者将调用SendToken(),它将安全令牌作为参数并返回安全令牌。
Microsoft WSE提供了诸如Microsoft.Web.Services3.Security.RequestSecurityToken和Microsoft.Web.Services3.Security.RequestSecurityTokenResponse的类,它们可以用作与STS通信的基础。 围绕这些类编写了少量其他代码,以简化其使用。 本文使用的TFIM Trust Client最初是在较早的developerWorks文章中引入的 。
代币管理器
该解决方案的一个重要方面是,对策略断言或输入和输出过滤器都不需要了解SAML令牌。 在WSE 3.0中,没有令牌管理器的令牌被解析为Microsoft.Web.Services3.Security.Tokens.IIssuedToken。 可以像对待其他任何安全令牌一样对待这种类型的对象,只是令牌是不透明的。
实作
本节详细介绍了上一节介绍的设计的重要方面。 完整的源代码可从本文结尾的“可下载资源”部分中获得。
创建自定义安全策略断言
清单2中显示的自定义策略断言必须将Microsoft.Web.Services3.Design.SecurityPolicyAssertion子类化,并实现以下方法:
- 公共重写Microsoft.Web.Services3.SoapFilter CreateClientInputFilter(FilterCreationContext上下文)
- 公共重写Microsoft.Web.Services3.SoapFilter CreateClientOutputFilter(FilterCreationContext上下文)
- 公共重写Microsoft.Web.Services3.SoapFilter CreateServiceInputFilter(FilterCreationContext上下文)
- 公共重写Microsoft.Web.Services3.SoapFilter CreateServiceOutputFilter(FilterCreationContext上下文)
- 公共重写System.Collections.Generic.IEnumerable <System.Collections.Generic.KeyValuePair <字符串,类型>> GetExtensions()
- 公共重写void ReadXml(XmlReader阅读器,IDictionary <string,Type>扩展名)
四个“创建”方法的功能可以修改输出消息并验证输入消息。 其他两种方法值得解释。 GetExtensions()方法将为此断言定义的不同配置名称的映射返回到实现类型。 这些名称然后在WSE策略配置文件中声明。 例如,上面的UsernameOverTransportAssertion类将返回从“ usernameOverTransportSecurity”到其类类型的映射。
ReadXml()方法用于读取WSE策略配置文件中设置的配置参数。 对于此解决方案,至少有一个配置参数:用于验证和颁发安全令牌的STS的URL。
清单2.策略声明实现
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Design;
using System.Diagnostics;
using System.Xml;
using System.Security.Policy;
namespace IBM.Tivoli.SOA.WSSM
{
public class TFIMSecurityAssertion : SecurityPolicyAssertion
{
private Uri _stsUrl = null;
private string _issuer = null;
private string _tokenType = null;
#region Fields
public Uri fimStsUrl
{
get { return _stsUrl; }
}
public string Issuer
{
get { return _issuer; }
}
public string TokenType
{
get { return _tokenType; }
}
#endregion
public TFIMSecurityAssertion() : base()
{
Trace.WriteLine("TFIMSecurityAssertion()");
}
public override Microsoft.Web.Services3.SoapFilter CreateClientInputFilter(
FilterCreationContext context)
{
return null;
}
public override Microsoft.Web.Services3.SoapFilter CreateClientOutputFilter(
FilterCreationContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
return new TFIMClientOutputFilter(this);
}
public override Microsoft.Web.Services3.SoapFilter CreateServiceInputFilter(
FilterCreationContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
return new TFIMServerInputFilter(this);
}
public override Microsoft.Web.Services3.SoapFilter CreateServiceOutputFilter(
FilterCreationContext context)
{
return null;
}
public override IEnumerable<KeyValuePair<string, Type>> GetExtensions()
{
//Gets the collection of policy extensions that are registered in the policy file.
return new KeyValuePair<string, Type>[] {
new KeyValuePair<string, Type>("TFIMSecurityAssertion", this.GetType()) };
}
public override void ReadXml(XmlReader reader, IDictionary<string, Type> extensions)
{
if (reader == null)
throw new ArgumentNullException("reader");
if (extensions == null)
throw new ArgumentNullException("extensions");
bool isEmpty = reader.IsEmptyElement;
base.ReadAttributes(reader);
reader.ReadStartElement("TFIMSecurityAssertion");
if (!isEmpty)
{
//We need the following:
// - STS endpoint
// - Issuer
if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "fimStsUrl")
{
reader.ReadStartElement();
string urlString = reader.ReadContentAsString();
_stsUrl = new Uri( urlString );
reader.ReadEndElement();
}
if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "fimIssuer")
{
reader.ReadStartElement();
_issuer = reader.ReadContentAsString();
reader.ReadEndElement();
}
if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "TokenType")
{
reader.ReadStartElement();
_tokenType = reader.ReadContentAsString();
reader.ReadEndElement();
}
reader.ReadEndElement();
}
}
public override void WriteXml(XmlWriter writer)
{
writer.WriteStartElement("TFIMSecurityAssertion");
writer.WriteStartElement("fimStsUrl");
writer.WriteString(_stsUrl.AbsoluteUri);
writer.WriteEndElement();
if (_issuer != null)
{
writer.WriteStartElement("fimIssuer");
writer.WriteString(_issuer);
writer.WriteEndElement();
}
if (_tokenType != null)
{
writer.WriteStartElement("TokenType");
writer.WriteString(_tokenType);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
}
}
客户端输出过滤器
客户端输出过滤器负责从TFIM请求SAML断言,并将其插入到传出消息中。 发送到TFIM的令牌是“客户端令牌”,它是从当前消息上下文中的凭据中提取的。
为了实现此功能,WSE 3.0默认Microsoft.Web.Services3.Security.SendSecurityFilter类被扩展。 在清单3中,从父Policy Assertion类提取配置信息。 这样的配置信息包括TFIM STS端点URL,以及对TFIM STS的WS-Trust请求中使用的Issuer参数的替代(可选)。
清单3中完成所有工作的方法是SecureMessage()。 在这种方法中,执行以下步骤:
- 检查当前消息的目的地,以构造“ AppliesTo”参数的值,以用于对TFIM STS的WS-Trust请求中。
- 尝试使用envelope.Context.Credentials.UltimateReceiver.GetClientToken <UsernameToken>()从消息上下文中提取当前的UsernameToken。
- 如果不存在UsernameToken,则使用当前用户的身份(使用System.Threading.Thread.CurrentPrincipal.Identity提取)创建一个新的用户名。
- 使用TFIM信任客户端将UsernameToken发送到TFIM。
- 将从TFIM返回的令牌添加到传出消息中的令牌列表中。
清单3.客户端输出过滤器实现
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Web.Services3.Security;
using IBM.Tivoli.FIM.TrustClient;
using Microsoft.Web.Services3.Security.Tokens;
using System.Collections;
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Addressing;
using System.Security.Principal;
namespace IBM.Tivoli.SOA.WSSM
{
public class TFIMClientOutputFilter : SecureConversationClientSendSecurityFilter
{
private static string DEFAULT_ISSUER = "urn:tivoli:soa:token-generator";
FIMTrustClient trustClient = null;
public TFIMClientOutputFilter(TFIMSecurityAssertion assertion)
: base(assertion)
{
//Get the issuer / appliesTo from the security assertion class
Uri stsEndpoint = assertion.fimStsUrl;
string issuer = DEFAULT_ISSUER;
if (assertion.Issuer != null)
issuer = assertion.Issuer;
trustClient = FIMTrustClientFactory.createTrustClient(
stsEndpoint, issuer, null);
if (assertion.TokenType != null)
trustClient.TokenType = assertion.TokenType;
}
public override void SecureMessage(SoapEnvelope envelope, Security security,
Microsoft.Web.Services3.Design.MessageProtectionRequirements request)
{
EndpointReference serviceEPR = null;
AddressingHeaders headers = envelope.Context.Addressing;
if (headers != null && headers.Destination != null)
{
Uri addressingTo = headers.Destination.Address.Value;
System.Diagnostics.Trace.WriteLine("AppliesTo: " + addressingTo.ToString());
serviceEPR = new EndpointReference(addressingTo);
}
else
{
serviceEPR = new EndpointReference(envelope.Context.WebRequest.RequestUri);
}
System.Diagnostics.Trace.WriteLine("Service URL: " + serviceEPR.Address.Value);
//Get the current user's identity
SecurityToken currentToken =
envelope.Context.Credentials.UltimateReceiver.GetClientToken<UsernameToken>();
if (currentToken == null)
{
//No token has been set yet, so we need to construct one based on the
//current user's principal
IPrincipal currentPrin = System.Threading.Thread.CurrentPrincipal;
if (currentPrin != null
&& currentPrin.Identity.Name != null
&& !"".Equals(currentPrin.Identity.Name))
{
String userName = currentPrin.Identity.Name;
currentToken = new UsernameToken(userName, "dummy");
envelope.Context.Credentials.UltimateReceiver.SetClientToken(currentToken);
}
}
System.Diagnostics.Trace.WriteLine("Current IdentityToken: " + currentToken);
if (currentToken != null)
{
SecurityToken responseToken = trustClient.SendToken(serviceEPR, currentToken);
//Add the SAML token returned to the outgoing message
//Do we want to replace whatever token is already there?
System.Diagnostics.Trace.WriteLine("Token from TFIM: " + responseToken);
security.Tokens.Add(responseToken);
}
}
}
}
服务输入过滤器
服务输入过滤器负责将SAML断言发送到TFIM,并将从TFIM返回的令牌设置为消息上下文中的“客户端令牌”。
清单4中完成所有工作的方法是ValidateMessageSecurity()。 在这种方法中,执行以下步骤:
- 检查当前消息的目的地,以构造要在TFIM STS的WS-Trust请求中使用的“ AppliesTo”参数的值。
- 在SOAP标头中提取第一个安全令牌。
- 使用TFIM信任客户端将此安全令牌发送到TFIM。
- 使用envelope.Context.Credentials.UltimateReceiver.SetClientToken(responseToken);将从TFIM返回的安全性令牌设置为客户端的身份令牌。
清单4.服务输入过滤器实现
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Web.Services3.Security;
using IBM.Tivoli.FIM.TrustClient;
using Microsoft.Web.Services3.Security.Tokens;
using System.Collections;
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Addressing;
namespace IBM.Tivoli.SOA.WSSM
{
public class TFIMServerInputFilter : SecureConversationServiceReceiveSecurityFilter
{
private static string DEFAULT_ISSUER = "urn:tivoli:soa:token-consumer";
FIMTrustClient trustClient = null;
public TFIMServerInputFilter(TFIMSecurityAssertion assertion)
: base(assertion)
{
//Get the issuer / appliesTo from the security assertion class
Uri stsEndpoint = assertion.fimStsUrl;
string issuer = DEFAULT_ISSUER;
if (assertion.Issuer != null)
issuer = assertion.Issuer;
trustClient = FIMTrustClientFactory.createTrustClient(stsEndpoint, issuer, null);
if ( assertion.TokenType != null)
trustClient.TokenType = assertion.TokenType;
}
public override void ValidateMessageSecurity(
Microsoft.Web.Services3.SoapEnvelope envelope,
Security security,
Microsoft.Web.Services3.Design.MessageProtectionRequirements request)
{
AddressingHeaders headers = envelope.Context.Addressing;
Uri addressingTo = headers.To.Value;
System.Diagnostics.Trace.WriteLine("AppliesTo: " + addressingTo.ToString());
EndpointReference serviceEPR = new EndpointReference(addressingTo);
//Extract the token(s) from the message
SecurityToken token = null;
if (security.Tokens.Count > 0)
{
//At a later date, we could add functionality to only send certain types
// of security tokens to TFIM. For the moment, we'll just send the first
// token we find.
IEnumerator e = security.Tokens.GetEnumerator();
e.MoveNext();
token = (SecurityToken)e.Current;
}
//Send the one we want off to TFIM
if (token != null)
{
System.Diagnostics.Trace.WriteLine("Sending token: " + token);
SecurityToken responseToken = trustClient.SendToken(serviceEPR, token);
System.Diagnostics.Trace.WriteLine("Response token: " + responseToken);
//The value returned from TFIM will be set as the identity
envelope.Context.Credentials.UltimateReceiver.SetClientToken(responseToken);
envelope.Context.IdentityToken = responseToken;
}
else
{
throw new SecurityFault("No valid token found in message");
}
}
}
}
使用解决方案
在本节中,将前面各节中描述的解决方案应用于示例Web服务应用程序,以演示所需的配置和运行时预期的行为。 可以从本文的“可下载资源”部分获得示例客户端和服务的代码。 为了方便起见,使用了TFIM Web服务安全管理(WSSM)组件中Echo应用程序的服务接口。
图6显示了将在本节中构建的环境。 在同一真实环境中启用客户端和Web服务的SAML可能不太可能(尽管很方便测试本文所附的代码)。 本文中该技术的一种更实际的应用是分别使用解决方案的每一部分。 例如:
- 启用SAML的Web服务客户端
可能的情况是Microsoft .NET中开发的表示层(例如,用户界面)需要与外部合作伙伴托管的服务进行通信。 由于此类服务与平台无关,广泛实施,因此通常被配置为接受SAML安全令牌。 - 启用SAML的Web服务
可能的情况是,需要使用Microsoft ASP.NET中托管的Web服务来向各种客户端提供服务,并且普通用户名令牌被认为不够丰富,无法断言调用方的身份。 诸如SAML之类的令牌类型可能是首选,因为它可以包含用户名以外的身份信息。
在这两种情况下,与TFIM集成都提供了额外的好处,即能够在本地管理域和伙伴的管理域之间执行身份映射。
图6.原型方案
在运行时,图6所示的活动顺序为:
- 用户尝试访问在前端ASP.NET应用程序服务器上运行的(受保护)资源,并向WebSEAL进行身份验证。
- WebSEAL将请求代理到前端ASP.NET应用程序服务器,并在HTTP标头中发送用户的序列化TAM凭证。
- Tivoli Access Manager for Microsoft .NET(AMNET)使用传入的iv-creds HTTP标头中的TAM凭证来设置前端ASP.NET应用程序服务器中请求者的身份。
- 前端ASP.NET应用程序服务器上正在访问的资源需要对后端ASP.NET应用程序服务器进行Web服务调用。 Web服务上的策略需要SAML 2.0声明。
- 调用前端ASP.NET应用程序服务器中的自定义客户端安全筛选器。 此客户端安全筛选器使用WS-Trust RequestSecurityToken消息中的用户名令牌中的TAM凭证中的用户名发送到TFIM STS。
- SAML 2.0断言返回到输出安全性筛选器。
- Web服务请求(现在包含SAML 2.0安全令牌)被发送到后端ASP.NET应用程序服务器。
- 后端ASP.NET应用程序服务器中的自定义服务安全筛选器被调用以使用SAML 2.0安全令牌。
- 服务安全过滤器将WS-Trust RequestSecurityToken消息中的SAML 2.0安全令牌发送到TFIM STS。
- 没有密码的用户名令牌将返回到服务安全筛选器。
- 服务安全筛选器在后端ASP.NET应用程序服务器中建立用户的身份。
TAM配置
如图6所示,Tivoli Access Manager(TAM)用于保护Echo客户机应用程序。 这涉及配置两个不同的TAM组件:
- WebSEAL
WebSEAL反向代理需要配置为与托管Echo客户端的IIS服务器的连接。 还需要将WebSEAL配置为跨联结发送已认证用户的凭证。 这是通过在创建联结时使用“ -c iv_creds”选项来完成的。
- 网络
AMNET认证插件通过WebSEAL服务器发送的TAM凭证在ASP.NET环境中建立用户身份。 有关如何配置AMNET的更多信息,请参考本文“ 相关主题”部分中推荐的文档。
WSE策略配置
本节介绍对Microsoft WSE应用程序标准应用程序配置文件的更改。 假定读者已经对在Microsoft .NET中构造Web服务应用程序有所了解,因为该配置没有详细说明。
回声客户端
清单5中显示的对应用程序配置文件的更改将启用跟踪并指定WSE策略配置文件的位置。 清单5被删节以显示特定于构建此解决方案的更改。
清单5. Web.config(节略)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
...
<microsoft.web.services3>
<diagnostics>
<trace enabled="true"
input="C:\temp\client-in.trace"
output="C:\temp\client-out.trace" />
<detailedErrors enabled="true" />
</diagnostics>
<policy fileName="wse3policyCache.config" />
</microsoft.web.services3>
</configuration>
清单6中所示的WSE策略配置指定TFIM安全性断言的使用,其中包括TFIM STS的位置。
清单6. wse3policyCache.config
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="TFIMSecurityAssertion"
type="IBM.Tivoli.SOA.WSSM.TFIMSecurityAssertion, IBM.Tivoli.SOA.WSSM"/>
</extensions>
<policy name="WSTrustClientSend">
<TFIMSecurityAssertion>
<fimStsUrl>http://[host]:[port]/TrustServer/SecurityTokenService</fimStsUrl>
</TFIMSecurityAssertion>
</policy>
</policies>
回声服务
清单7中显示的对应用程序配置文件的更改将启用跟踪并指定WSE策略配置文件的位置。 清单7被删节以显示特定于构建此解决方案的更改。 TrustedUsernameTokenManager
已配置为禁用针对本地用户存储对UsernameToken中的用户进行身份验证的默认.NET功能。
清单7. Web.config(节略)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
...
<webServices>
<soapExtensionImporterTypes>
<add
type="Microsoft.Web.Services3.Description.WseExtensionImporter, \
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
<soapServerProtocolFactory
type="Microsoft.Web.Services3.WseProtocolFactory, \
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</webServices>
</system.web>
<microsoft.web.services3>
<security>
<securityTokenManager>
<add namespace=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
localName="UsernameToken" type=
"IBM.Tivoli.FIM.TrustClient.Tokens.TrustedUsernameTokenManager, FIMTrustClient" />
</securityTokenManager>
</security>
<diagnostics>
<trace enabled="true"
input="C:\temp\service-in.trace"
output="C:\temp\service-out.trace" />
<detailedErrors enabled="true" />
</diagnostics>
<policy fileName="wse3policyCache.config" />
</microsoft.web.services3>
</configuration>
清单8中所示的WSE策略配置指定TFIM安全性断言的使用,其中包括TFIM STS的位置。
清单8. wse3policyCache.config
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="TFIMSecurityAssertion"
type="IBM.Tivoli.SOA.WSSM.TFIMSecurityAssertion, IBM.Tivoli.SOA.WSSM"/>
</extensions>
<policy name="WSTrustServiceReceive">
<TFIMSecurityAssertion>
<fimStsUrl>http://[host]:[port]/TrustServer/SecurityTokenService</fimStsUrl>
</TFIMSecurityAssertion>
</policy>
</policies>
TFIM配置
该解决方案利用TFIM STS的功能为.NET Web服务提供与令牌无关的身份验证。 本节介绍如何配置TFIM STS来为客户端发出SAML v2.0声明并为服务器使用SAML v2.0声明。 在这两种情况下,要交换SAML断言的令牌都是UsernameToken。
当示例中的客户端或服务器筛选器构造RequestSecurityToken(RST)WS-Trust消息以发送到TFIM时,AppliesTo值将设置为接收服务的URL。 如果需要,可以为环境中的每个服务配置单独的信任链对。 对于该示例,我们将创建一对可应用于不同服务的信任链。
表1显示了客户端输出过滤器的信任链配置。 注意,颁发者的值为urn:tivoli:soa:token-generator
。 这是客户机输出过滤器为所有WS-Trust请求设置的缺省值。
表1.客户端输出的TFIM信任链
配置参数 | 描述 |
---|---|
适用于 | * |
发行人 | 骨灰盒:tivoli:soa:代币生成器 |
请求类型 | 验证 |
令牌类型(可选) | 标准令牌类型:SAML v2.0 |
链 | 默认用户名令牌; 模式=验证 |
默认SAML v2.0令牌; 模式=问题 |
表2显示了服务输入过滤器的信任链配置。 在这种情况下,发行者是urn:tivoli:soa:token-consumer
。 这是服务输入过滤器为所有WS-Trust请求设置的缺省值。
表2.用于服务输入的TFIM信任链
配置参数 | 描述 |
---|---|
适用于 | * |
发行人 | urn:tivoli:soa:代币消费者 |
请求类型 | 验证 |
令牌类型(可选) | 标准令牌类型:用户名 |
链 | 默认SAML v2.0令牌; 模式=验证 |
默认用户名令牌; 模式=问题 |
互通性
已针对TFIM WSSM 6.1.1版随附的基于J2EE™的客户端和服务成功测试了该客户端和服务。
挑战性
该解决方案的优势在于,可以在不修改应用程序或其部署的情况下随时更改所使用的令牌类型。 例如,将来的公司安全策略可能要求通过X-509证书而不是SAML v2.0断言来在线使用。 这种方法并非没有缺点。 由于令牌是不透明的,因此无法在运行时使用SAML断言中的属性数据。 SAML断言可能包含扩展属性,并且由于该解决方案使用TFIM来仅提取名称,因此这些其他属性会丢失。
未来的工作
该解决方案可以通过多种方式扩展:
- 在服务使用者(客户端)方面,客户端输出过滤器在将其发送到TFIM时以Username令牌表示当前经过身份验证的身份。 这意味着仅发送用户名,从而限制了可以在TFIM返回的安全令牌中包含哪些信息。 可以增强该解决方案,以从当前经过身份验证的身份中提取其他信息,并以更丰富的令牌格式(例如SAML 1.0声明)来表示此信息,以发送到TFIM STS。 一个示例是客户端应用程序使用AMNET,它可以使TAM凭证的内容可用于TFIM中的信任模块链。
- 在服务方面,服务输入过滤器期望从TFIM STS返回用户名令牌。 来自用户名令牌的用户名用于在Microsoft .NET中建立身份。 一种可能的增强是允许服务输入过滤器接收包含其他属性的更复杂的令牌类型,并使用AMNET以TAM凭据格式设置用户身份。
- 整个解决方案可以移植到Windows Communication Foundation(WCF)。 WCF替代了WSE 3.0,并且是.NET Framework 3.0的一部分
结论
本文介绍了如何通过使用Tivoli Federated Identity Manager及其安全令牌服务在Microsoft .NET中集成其他安全令牌类型。 这种方法相对于其他方法的优势在于,上述实现几乎可以在没有任何代码修改的情况下适用于任何令牌类型-TFIM中只是不同的信任模块链配置。 这使其成为一种灵活的解决方案,可以使SOA环境适应未来的需求。
翻译自: https://www.ibm.com/developerworks/tivoli/library/t-samlwse/index.html
cas和saml