首先我们来说说STS(Security Token Service)的最简生命周期,当然这是要基于WIF(Windows Identity Foundation)框架的。
一. 分析传入数据的可用性,并创建SignInRequestMessage
WSFederationMessage提供CreateFromUri以及CreateFromNameValueCollection等简单的创建入口(本例使用CreateFromUri)
二. 通过对SignInRequestMessage的解析以及确认,生成SignInResponseMessage
1.创建SecurityTokenServiceConfiguration以驱动自定义SecurityTokenService
a)自定义的SecurityTokenService需要对以下的内容进行定义:
* ClaimsIdentity发布的内容(Claims的ClaimsType和Value需要搭建STS人自己定义)
* Scope的定义
b) Scope无非是对请求STS端应用以及其他的Policy进行定义,其中SignedCertificate必须要进行定义。
2.创建WSFederationSerializer以对SignInRequestMessage进行处理,并序列化SignInResponseMessage
3.验证SignInRequestMessage 内容的有效性(如果STS使用的是Windows 身份验证,可以忽略此项)
4. 获取验证过的自定义的Identity(或者系统Identity),结合SignInRequestMessage,通过自定义SecurityTokenService进行发布(Issue),获取RequestSecurityTokenResponse
5. 获取最终的SignInResponseMessage
声明周期即以上的部分,这是最简单的方式,其余的需要进行自定义的部分,可以在这简单的实例基础上进行添加。
以下是代码部分
一. 自定义Security Token Service
public class CustomSTS : SecurityTokenService
{
private SigningCredentials _signingCreds;
private EncryptingCredentials _encryptingCreds;
public CustomSTS(SecurityTokenServiceConfiguration configuration) :base(configuration)
{
_signingCreds = new X509SigningCredentials(new X509Certificate2(@"C:\Users\Administrator\Desktop\ForNewSTS.pfx","1qaz2wsxE"));
_encryptingCreds = new X509EncryptingCredentials(new X509Certificate2(@"C:\Users\Administrator\Desktop\ForNewSTS.pfx", "1qaz2wsxE"));
}
protected override Microsoft.IdentityModel.Claims.IClaimsIdentity GetOutputClaimsIdentity(Microsoft.IdentityModel.Claims.IClaimsPrincipal principal, Microsoft.IdentityModel.Protocols.WSTrust.RequestSecurityToken request, Scope scope)
{
ClaimsIdentity outputIdentity = new ClaimsIdentity();
outputIdentity.Claims.Add(new Claim("http://test.com/c/c","/create"));
return outputIdentity;
}
protected override Scope GetScope(Microsoft.IdentityModel.Claims.IClaimsPrincipal principal, Microsoft.IdentityModel.Protocols.WSTrust.RequestSecurityToken request)
{
Scope sc = new Scope(request.AppliesTo.Uri.AbsoluteUri, _signingCreds);
sc.TokenEncryptionRequired = false;
sc.ReplyToAddress = request.ReplyTo;
return sc;
}
}
二. 生成SignInResponseMessage的简易流程
private SignInResponseMessage ProcessSignInRequest(SignInRequestMessage requestMessage)
{
// Ensure that the requestMessage has the required wtrealm parameter
if (String.IsNullOrEmpty(requestMessage.Realm))
{
throw new InvalidOperationException("Missing realm");
}
//set the SecurityTokenService Configuration Name, this name should be unique.
SecurityTokenServiceConfiguration stsconfig = new SecurityTokenServiceConfiguration("PassiveFlowSTS");
// Create our STS backend
SecurityTokenService sts = new CustomSTS(stsconfig);
// Create the WS-Federation serializer to process the request and create the response
WSFederationSerializer federationSerializer = new WSFederationSerializer();
// Create RST from the request
RequestSecurityToken request = federationSerializer.CreateRequest(requestMessage, new WSTrustSerializationContext());
// Get RSTR from our STS backend
RequestSecurityTokenResponse response = sts.Issue((IClaimsPrincipal)GenericAPrincipal(), request);
// Create Response message from the RSTR
return new SignInResponseMessage(new Uri(response.ReplyTo),
federationSerializer.GetResponseAsString(response, new WSTrustSerializationContext()));
}
public IClaimsPrincipal GenericAPrincipal()
{
IClaimsIdentity localIdentity = new ClaimsIdentity("testFederation", "http://xxx.com/c/test", "somebody in STS");
List<IClaimsIdentity> list = new List<IClaimsIdentity>();
list.Add(localIdentity);
ClaimsPrincipal p = new ClaimsPrincipal(list);
return p;
}