2010-08-24 101 views
3

this question相关,我有一个自定义的UserNamePasswordValidator,它登录到我们的内部API。作为此登录的一部分,我可以在系统中发现用户的角色。可以将自定义的UserNamePasswordValidator用作角色提供者吗?

我想以后在PrincipalPermissionAttribute需求服务上的方法使用这些,例如:

[OperationContract] 
[PrincipalPermission(SecurityAction.Demand, Role = "System Administrator")] 
public string HelloWorld() 
{ /* ... */ } 
+0

罗杰,你管理解决这个问题?我想要做同样的事情。 – 2011-04-15 08:42:26

回答

6

要扩大拉吉斯拉夫的回答是:

号定制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> 

关联与您的服务行为。

覆盖以返回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")] 
+0

你能否回答http://stackoverflow.com/questions/9584198/authentication-service-using-wcf? – Lijo 2012-03-06 13:12:41

+0

@Lijo不,因为两者不相关。 – 2012-03-06 14:18:27

2

我觉得不能因为你需要创建自定义的校长。之所以我认为你不能在验证器中这样做,是因为我在某处读取了验证器在不同于运行上下文的线程中运行。我从来没有检查过,但让我们假设它确实如此。基于这个假设,验证器中的Principal集不会用在WCF操作中。您必须创建custom autorization或自定义角色提供程序。

相关问题