扩展拉迪斯拉夫的回答:
没有。自定义 UserNamePasswordValidator 不能用作角色提供者。 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 以返回从 ServiceCredentialsSecurityTokenManager 派生的 MySecurityTokenManager。对此,覆盖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")]