我使用UserNamePasswordValidator实现了自定义身份验证。
根据项目要求,我需要四个输入参数进行身份验证(用户名,密码,SiteID,BrandID)。
但Validate Method只接受两个参数:Validate(string userName,string password)
问题:
1)如何向验证方法发送两个以上的参数?
2)是否有其他方法可以使用自己的验证方法定义WCF身份验证?
谢谢,
拉姆
答案 0 :(得分:0)
<强> 1。连接的基本解决方案
可能是最快的方式,最简单的方法是连接用户名,SiteID和BrandID (用/或分隔 - 并进行某种转义以防止使用分隔字符)用户名标题并创建一个CustomValidator。
--------------------------- 修改 ------------ ---------------
<强> 2。有一些方法可以传递一些**额外标题,并使用OperationContext
。**
我还将展示如何设置声明权限
为了做到这一点,你可以使用JuvalLöwy的课程。他实现了你可以使用的GenericContext<T>
。
GenericContext<T>
封装了访问标题的机制。
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在客户端
传递额外的标题:
static void Main(string[] args)
{
// provide identity as headers
var extraHeaders = new ExtraHeaders
{
Username="manager",
Password= "password",
BranchId = "Branch2",
SiteId = "Site2"
};
MyContractClient proxy = new MyContractClient(extraHeaders);
proxy.MyMethod();
proxy.Close();
}
代理必须稍微更改一下(不是 Visual Studio 或 svcutil.exe 代):
class MyContractClient : HeaderClientBase<IMyContract, ExtraHeaders>, IMyContract
{
public MyContractClient(string key,string value) : base(key,value)
{}
public void MyMethod()
{
Channel.MyMethod();
}
}
2.3 - 在服务器端添加声明性权限
具有
的声明性许可
[PrincipalPermission(SecurityAction.Demand, Role = "Manager")]
class MyService : IMyContract
{
[PrincipalPermission(SecurityAction.Demand, Role = "Manager")]
public void MyMethod()
{
var extraHeaders = ExtraHeadersContext.Current;
if (extraHeaders != null)
{
//Console.WriteLine("Extra headers: (BranchId:{0}, SiteId:{1}) ", extraHeaders.BranchId, extraHeaders.SiteId);
Console.WriteLine("Service call from : {{{0}}}", extraHeaders.Username);
}
}
}
2.4添加serviceAuthorizationBehavior以将标识粘贴到使用
<behaviors>
<serviceBehaviors>
<behavior name="customIdentificationBehavior">
<serviceAuthorization principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="Security.HttpContextPrincipalPolicy,Host" />
</authorizationPolicies>
</serviceAuthorization>
</behavior>
2.5实施serviceAuthorizationBehvior
该行为的目标是为调用者分配Principal和Identity。
namespace Security
{
public class HttpContextPrincipalPolicy : IAuthorizationPolicy
{
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
try
{
var extraHeaders = ExtraHeadersContext.Current;
if (extraHeaders != null)
{
IPrincipal principal = new CustomPrincipal(
new GenericIdentity(extraHeaders.Username, "Custom Provider"),extraHeaders);
evaluationContext.Properties["Principal"] = principal;
// Put user here so it can be used for declarative access on methods
evaluationContext.Properties["Identities"] = new List<IIdentity>() { principal.Identity };
}
else
{
SetAnonymousPrincipal(evaluationContext);
}
}
catch (Exception)
{
SetAnonymousPrincipal(evaluationContext);
}
return true;
}
}
}
2.6 CustomPrincipal类负责让用户担任角色
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];
}
链接到完整的工作源代码:http://1drv.ms/1OqPMUM
链接到优秀的Juval Lowy的代码: 在页面http://www.idesign.net/Downloads中查找“上下文绑定作为自定义上下文”以获得GenericContext类 如果你花时间在WCF上,他的书很棒
此致