使用System.ServiceModel.ServiceAuthenticationManager进行自定义WCF身份验证?

fre*_*ain 16 authentication wcf

我正在进行自定义WCF身份验证和授权,并找到一些关于UserNamePasswordValidatorServiceAuthorizationManager的文章.

我还发现了使用自定义System.ServiceModel的线索.ServiceAuthenticationManager(死链接 ),但msdn并没有详细说明它(http://msdn.microsoft.com/en-us/library/system.servicemodel.serviceauthenticationmanager.aspx).

所以我在这里:任何人都更了解ServiceAuthenticationManager?

通常,您将如何设置自定义WCF身份验证?

Mik*_*win 36

你是对的,关于这个的文档根本没有帮助.

我使用这个类的方法如下.将Authenticate()方法重写为:

  1. 从传入消息中提取身份验证令牌(例如用户名/密码)
  2. 验证令牌并使用它们来创建IPrincipal对象.这将是在调用服务操作期间使用的主体.
  3. 将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;
}
Run Code Online (Sandbox Code Playgroud)

然后添加自定义授权策略

  1. 从消息中检索IPrincipal(使用System.ServiceModel.EvaluationContext.Current.IncomingMessageProperties集合).
  2. 将IPrincipal推送到EvaluationContext.Properties集合中
  3. 基于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;
}
Run Code Online (Sandbox Code Playgroud)

在服务行为配置中,您需要设置principalPermissionMode ="Custom",以便WCF将IPrincipal设置为实际服务操作调用的执行线程上的主体.

<serviceAuthorization principalPermissionMode="Custom"...
Run Code Online (Sandbox Code Playgroud)

  • @TobyJ:如果您只想使用ClientCredentials设置的用户名和密码,您确实应该使用自定义UserNamePasswordValidator.正如您所说,我描述的解决方案是针对自定义标头.在我的情况下,我正在使用具有用户名和密码作为自定义消息头的遗留服务,而不是作为HTTP或SOAP标准头的一部分.很抱歉没有说清楚...... (3认同)