1.连接的基本解决方案
可能是最快且最简单的方法是在 用户名标题并创建一个CustomValidator。
--------------- 编辑 ------------ ---------------
2。有一些方法可以传递一些**额外的标头,并使用OperationContext.**
我还将展示如何设置声明性权限
为此,您可以使用 Juval Löwy 的课程。他实现了一个你可以使用的GenericContext<T>。
GenericContext<T> 封装了访问标头的机制。
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 在客户端
传递额外的标题:
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 和一个身份。
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 中查找“Context bindings as custom context”以获得 GenericContext 类
如果你花时间在 WCF 上,他的书很棒
问候