你是对的,这方面的文档根本没有帮助。
我使用这个类的方式如下。将 Authenticate() 方法重写为:
- 从传入消息中提取身份验证令牌(例如用户名/密码)
- 验证令牌并使用它们创建 IPrincipal 对象。这将是调用服务操作期间使用的主体。
- 将 IPrincipal 对象添加到 message.Properties 集合,以便稍后在 WCF 处理管道中使用它
此时您不能只设置线程主体,因为它稍后会被 WCF 更改。
ServiceAuthenticationManager.Authenticate() 方法中的代码如下所示:
public override ReadOnlyCollection<IAuthorizationPolicy> Authenticate(ReadOnlyCollection<IAuthorizationPolicy> authPolicy, Uri listenUri, ref Message message)
{
int tokenPosition = message.Headers.FindHeader("Token", "http://customnamespace.org");
string token = message.Headers.GetHeader<string>(tokenPosition);
IPrincipal user = new CustomPrincipal(token);
message.Properties["Principal"] = user;
return authPolicy;
}
然后你添加一个自定义的授权策略,
- 从消息中检索 IPrincipal(使用 System.ServiceModel.EvaluationContext.Current.IncomingMessageProperties 集合)。
- 将 IPrincipal 推送到 EvaluationContext.Properties 集合中
- 根据 IPrincipal.IsInRole() 方法进行声明
IAuthorizationPolicy() 方法中的代码如下所示
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
IPrincipal user = OperationContext.Current.IncomingMessageProperties["Principal"] as IPrincipal;
evaluationContext.Properties["Principal"] = user;
evaluationContext.Properties["Identities"] = new List<IIdentity> { user.Identity };
IList<Claim> roleClaims = this.GetRoleClaims(user);
evaluationContext.AddClaimSet(this, new DefaultClaimSet(this.Issuer, roleClaims));
return true;
}
在服务行为配置中,您需要设置 principalPermissionMode="Custom",以便 WCF 将 IPrincipal 设置为执行线程上的主体,以进行实际的服务操作调用。
<serviceAuthorization principalPermissionMode="Custom"...