要扩展Ladislav的答案:
不可以。自定义用户名密码验证程序不能用作角色提供程序。usernamepasswordvalidator在一个独立的上下文(或线程,或其他)中运行,该上下文与您要处理的operationcontext无关。
您需要做的是实现自定义授权。我发现
this page
做这个最有用。警告:在你进入有趣的部分之前,有很多管道。
基本上,你从
ServiceCredentials
-派生类,注册于
App.config
如下:
<serviceBehaviors>
<behavior name="...">
<serviceAuthorization principalPermissionMode="Custom" />
<serviceCredentials type="MyNamespace.MyServiceCredentials, MyAssembly">
<userNameAuthentication userNamePasswordValidationMode="Custom" />
<serviceCertificate etc. />
</serviceCredentials>
将行为与服务关联起来。
重写
ServiceCredentials.CreateSecurityTokenManager
归还
MySecurityTokenManager
来源于
ServiceCredentialsSecurityTokenManager
. 在这一点上,超越
CreateSecurityTokenAuthenticator
返回一个
MySecurityTokenAuthenticator
. 那应该来自
CustomUserNameSecurityTokenAuthenticator
. 在这一点上,重写
ValidateUserNamePasswordCore
. 调用基类,它将返回授权策略列表。
在该列表中,添加一个新列表:
MyAuthorizationPolicy
,实现
IAuthorizationPolicy
. 在这一点上,你只需要(哈)做以下事情:
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
IList<IIdentity> identities = GetIdentities(evaluationContext);
// Find the GenericIdentity with our user-name in it.
IIdentity currentIdentity = identities.SingleOrDefault(
i => i is GenericIdentity &&
StringComparer.OrdinalIgnoreCase.Equals(i.Name, UserName));
if (currentIdentity == null)
throw new InvalidOperationException("No Identity found");
// Replace the GenericIdentity with a new one.
identities.Remove(currentIdentity);
var newIdentity =
new GenericIdentity(_userName, currentIdentity.AuthenticationType);
identities.Add(newIdentity);
// This makes it available as
// ServiceSecurityContext.Current.PrimaryIdentity later.
evaluationContext.Properties["PrimaryIdentity"] = newIdentity;
// This makes it available as Thread.CurrentPrincipal.
IPrincipal newPrincipal = new GenericPrincipal(newIdentity, _roles);
evaluationContext.Properties["Principal"] = newPrincipal;
return true;
}
private static IList<IIdentity> GetIdentities(
EvaluationContext evaluationContext)
{
object identitiesProperty;
if (!evaluationContext.Properties.TryGetValue(
"Identities", out identitiesProperty))
throw new InvalidOperationException("No Identity found");
var identities = identitiesProperty as IList<IIdentity>;
if (identities == null)
throw new InvalidOperationException("No Identity found");
return identities;
}
然后,在完成了这些工作之后,您可以用
PrincipalPermission
:
[PrincipalPermission(SecurityAction.Demand, Role = "Editor")]