允许匿名访问单个WCF服务方法

时间:2014-03-10 09:47:34

标签: c# wcf

我有一个带有邮件安全性和用户名凭据的WCF服务。我的大多数方法都是以

开头的
[PrincipalPermission(SecurityAction.Demand, Role = ConstStrings.Roles.Admin)]

并且这些方法应该仅由经过身份验证的用户调用。

我想添加一个匿名调用的方法,但收到错误:

  

未提供用户名。在ClientCredentials中指定用户名。

我喜欢类似于MVC的[AllowAnonymous]属性

3 个答案:

答案 0 :(得分:7)

一种选择是实施您自己的ServiceAuthorizationManager并使用您自己的自定义属性而不是PrincipalPermission

基本上,您必须继承ServiceAuthorizationManager。通过在web.config中添加以下配置,将其插入到WCF管道中(假设您的类在Org.Namespace命名空间中被调用' CustomAuthorizationManager'。

<behaviors>
  <serviceBehaviors>
    <behavior>
      <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpGetEnabled="true" />
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="true" />
      <!--<serviceAuthorization impersonateCallerForAllOperations="true" />-->
      <serviceAuthorization serviceAuthorizationManagerType="Org.Namespace.CustomAuthorizationManager, Org.Namespace" />
    </behavior>
  </serviceBehaviors>
</behaviors>

在自定义授权类中,您必须覆盖CheckAccessCore方法,如下所示。在那里,您可以检查您创建的自定义属性(这将是您将使用您想要的任何属性创建的普通.Net属性。)

    protected override bool CheckAccessCore(OperationContext operationContext)
    {
        string action = operationContext.IncomingMessageHeaders.Action;
        DispatchOperation operation = operationContext.EndpointDispatcher.DispatchRuntime.Operations.FirstOrDefault(o => o.Action == action);
        Type hostType = operationContext.Host.Description.ServiceType;
        MethodInfo method = hostType.GetMethod(operation.Name);
        var myCustomAttributeOnMethod = method.GetCustomAttributes(true).Where(a => a.GetType() == typeof (MyCustomAttribute)).Cast<MyCustomAttribute>();
    .
    .
    .
    }        

现在您可以检查自定义属性并根据需要执行任何功能。例如,如果自定义属性&#34; AllowAnonymous&#34;标志已设置,您可以跳过角色检查。否则,您可能会获得用户的Windows身份并检查他们是否处于特定角色。

当然,您需要使用自定义属性而不是PrincipalPermission来装饰相关方法。

总而言之,基本上您正在使用自己的普通自定义.Net属性来装饰所有方法,该属性提供了一些信息。即此方法允许匿名,此方法需要此角色等。然后,您更新web.config文件以告知WCF使用您自己的服务授权管理器。您可以实现自己的服务授权管理器,您可以访问正在调用的方法,检查它的自定义属性并说出&#34; Yay&#34;或者&#34; Nay&#34;相应

答案 1 :(得分:1)

您可以按照上面的建议进行操作,然后使用此代码段检查调用的特定方法:

var requestedOperation = 
    OperationContext.Current.IncomingMessageHeaders.Action.Split('/').Last();

这将产生以下结果:

public override void Validate(string userName, string password)
{
    if(String.IsNullOrEmpty(userName) && String.IsNullOrEmpty(password))
    {
        var requestedOperation = 
            OperationContext.Current.IncomingMessageHeaders.Action.Split('/').Last();

        if("myAnonymousOperation" == requestedOperation)
        {        
            // Allow anonymous access here.
            return;
        }
    }

    // Allow/deny users that provide credentials
    ValidateOtherCredentials(userName, password);
}

答案 2 :(得分:0)

您可以实现this教程中显示的自定义UserNamePasswordValidator。此验证器需要实现Validate方法,以允许匿名访问。

public override void Validate(string userName, string password)
{
    if(String.IsNullOrEmpty(userName) && String.IsNullOrEmpty(password))
    {
        // Allow anonymous access here.
        return;
    }

    // Allow/deny users that provide credentials
    ValidateOtherCredentials(userName, password);
}

注意:如果您允许匿名访问,则使用PrincipalPermission的授权过程仍需要凭据。我不确定,但这可能会在运行时导致异常。