.net WCF自定义身份验证问题

.net WCF自定义身份验证问题,.net,web-services,wcf,authentication,restful-authentication,.net,Web Services,Wcf,Authentication,Restful Authentication,我已经用UserNamePasswordValidator实现了自定义身份验证 根据项目要求,我需要四个身份验证输入参数(用户名、密码、SiteID、BrandID) 但是Validate方法只接受两个参数:Validate(字符串用户名、字符串密码) 问题: 1) 如何发送两个以上的参数来验证方法 2) 是否有其他方法可以使用自己的验证方法定义WCF身份验证 谢谢, Ram1。带串联的基本解决方案 最快也是最简单的方法可能是在用户名标题中连接用户名、SiteID和BrandID(用/or-分隔

我已经用UserNamePasswordValidator实现了自定义身份验证

根据项目要求,我需要四个身份验证输入参数(用户名、密码、SiteID、BrandID)

但是Validate方法只接受两个参数:Validate(字符串用户名、字符串密码)

问题:

1) 如何发送两个以上的参数来验证方法

2) 是否有其他方法可以使用自己的验证方法定义WCF身份验证

谢谢,


Ram1。带串联的基本解决方案

最快也是最简单的方法可能是用户名标题中连接用户名、SiteID和BrandID(用/or-分隔,并进行某种转义以防止使用分隔字符),然后创建CustomValidator

---------------------------编辑---------------------------

2。有一些方法可以传递**额外的标题,并使用
OperationContext
**

我还将演示如何放置声明性权限

为了做到这一点,您可以使用Juval Löwy类。他实现了一个您可以使用的
GenericContext

GenericContext
封装了访问头的机制

2.1创建共享库

要共享来自客户端和服务器的一些数据,请将其作为soap头传递

[DataContract]
public class ExtraHeaders
{
    [DataMember]
    public String Username { get; set; }
    [DataMember]
    public String Password { get; set; }
    [DataMember]
    public String BranchId { get; set; }
    [DataMember]
    public String SiteId { get; set; }
}
2.2在客户端

<behaviors>
  <serviceBehaviors>
    <behavior name="customIdentificationBehavior">
      <serviceAuthorization principalPermissionMode="Custom">
        <authorizationPolicies>
          <add policyType="Security.HttpContextPrincipalPolicy,Host" />
        </authorizationPolicies>
      </serviceAuthorization>
    </behavior>
public class CustomPrincipal : IPrincipal
{
    private ExtraHeaders headers;
    private IIdentity identity;

    public CustomPrincipal(IIdentity identity, ExtraHeaders headers = null)
    {
        this.identity = identity;
        this.headers = headers;
    }
    public IIdentity Identity
    {
        get { return identity; }
    }
    public bool IsInRole(string role)
    {
        String[] roles;
        if (identity.Name == "manager")
            roles = new string[1] { "Manager" };
        else
            roles = new string[1] { "User" };
        return roles.Contains(role);
    }
}
传递额外的标题:

必须稍微更改代理(不是Visual Studiosvcutil.exe生成):

2.4添加serviceAuthorizationBehavior以将标识粘贴到使用中

<behaviors>
  <serviceBehaviors>
    <behavior name="customIdentificationBehavior">
      <serviceAuthorization principalPermissionMode="Custom">
        <authorizationPolicies>
          <add policyType="Security.HttpContextPrincipalPolicy,Host" />
        </authorizationPolicies>
      </serviceAuthorization>
    </behavior>
public class CustomPrincipal : IPrincipal
{
    private ExtraHeaders headers;
    private IIdentity identity;

    public CustomPrincipal(IIdentity identity, ExtraHeaders headers = null)
    {
        this.identity = identity;
        this.headers = headers;
    }
    public IIdentity Identity
    {
        get { return identity; }
    }
    public bool IsInRole(string role)
    {
        String[] roles;
        if (identity.Name == "manager")
            roles = new string[1] { "Manager" };
        else
            roles = new string[1] { "User" };
        return roles.Contains(role);
    }
}
结论

在幕后,Juval的类读取(服务器端)和写入(客户端)头

例如,摘录:

     if(OperationContext.Current.IncomingMessageProperties.ContainsKey(ContextMessageProperty.Name))
     {
        ContextMessageProperty contextProperty = OperationContext.Current.IncomingMessageProperties[ContextMessageProperty.Name] as ContextMessageProperty;
        if(contextProperty.Context.ContainsKey(key) == false)
        {
           return null;
        }
        return contextProperty.Context[key]; 
     }
链接到完整的工作源代码:

链接到优秀的Juval Lowy代码: 在页面中查找“作为自定义上下文的上下文绑定”,以获得GenericContext类 如果你花时间在WCF上,他的书会很棒


问候

谢谢。将使用变量的串联。确定。所以我也尝试了另一种方法,移除了CustomValidator。已实现OperationContext并在额外标头中传递变量。但是我如何将用户信息与当前请求链接。我如何以这种方式实现自定义原则和标识。根据Löwy的说法,您可以将任何DataContract@ram,我刚刚对我文章的第二部分做了一个大的编辑来回答你的评论。现在还有一个指向VS的链接solution@ram-臭虫!对不起,我忘了提交我的修改。这里是postedI编辑我的帖子,向您展示OperationContext/GenericContext代码。希望它有用
     if(OperationContext.Current.IncomingMessageProperties.ContainsKey(ContextMessageProperty.Name))
     {
        ContextMessageProperty contextProperty = OperationContext.Current.IncomingMessageProperties[ContextMessageProperty.Name] as ContextMessageProperty;
        if(contextProperty.Context.ContainsKey(key) == false)
        {
           return null;
        }
        return contextProperty.Context[key]; 
     }