WCF 自定义身份验证问题
WCF Custom Authentication Issue
我已经使用 UserNamePasswordValidator 实现了自定义身份验证。
根据项目要求,我需要四个输入参数进行身份验证(用户名、密码、网站ID、品牌ID)。
但是 Validate 方法只接受两个参数:Validate(string userName, string password)
问题:
1) 如何向验证方法发送两个以上的参数?
2) 是否有任何其他方法可以使用自己的验证方法定义 WCF 身份验证?
谢谢,
内存
1.串联的基本解决方案
可能最快和最简单的方法是 连接用户名、站点 ID 和品牌 ID(用 / 或 - 分隔并进行某种转义以防止使用分隔符)在 Username header 中创建一个 CustomValidator.
---------------------------- 编辑 ------ --------------------
2。有一些方法可以传递一些 **extra headers,并使用 OperationContext
.**
我还将展示如何放置 声明性权限
为此,您可以使用 Juval Löwy 的 classes。他实现了一个你可以使用的GenericContext<T>
。
GenericContext<T>
封装了访问 header 的机制。
2.1 创建共享库
从客户端和服务器共享一些数据,作为 soap 传递 headers
[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客户端
传递额外的 headers:
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
该行为的目标是为调用者分配一个委托人和一个身份。
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 class 负责将用户置于角色
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 的 class 读(服务器端)和写(客户端)header。
摘录,例如:
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];
}
Link 到完整的工作源代码:http://1drv.ms/1OqPMUM
Link 优秀的 Juval Lowy 代码:
在页面 http://www.idesign.net/Downloads 中查找 "Context bindings as custom context" 以获得 GenericContext class
如果你花时间在 WCF 上,他的书很棒
此致
我已经使用 UserNamePasswordValidator 实现了自定义身份验证。
根据项目要求,我需要四个输入参数进行身份验证(用户名、密码、网站ID、品牌ID)。
但是 Validate 方法只接受两个参数:Validate(string userName, string password)
问题:
1) 如何向验证方法发送两个以上的参数?
2) 是否有任何其他方法可以使用自己的验证方法定义 WCF 身份验证?
谢谢,
内存
1.串联的基本解决方案
可能最快和最简单的方法是 连接用户名、站点 ID 和品牌 ID(用 / 或 - 分隔并进行某种转义以防止使用分隔符)在 Username header 中创建一个 CustomValidator.
---------------------------- 编辑 ------ --------------------
2。有一些方法可以传递一些 **extra headers,并使用 OperationContext
.**
我还将展示如何放置 声明性权限
为此,您可以使用 Juval Löwy 的 classes。他实现了一个你可以使用的GenericContext<T>
。
GenericContext<T>
封装了访问 header 的机制。
2.1 创建共享库
从客户端和服务器共享一些数据,作为 soap 传递 headers
[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客户端
传递额外的 headers:
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
该行为的目标是为调用者分配一个委托人和一个身份。
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 class 负责将用户置于角色
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 的 class 读(服务器端)和写(客户端)header。
摘录,例如:
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];
}
Link 到完整的工作源代码:http://1drv.ms/1OqPMUM
Link 优秀的 Juval Lowy 代码: 在页面 http://www.idesign.net/Downloads 中查找 "Context bindings as custom context" 以获得 GenericContext class 如果你花时间在 WCF 上,他的书很棒
此致