2010-08-24 102 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或自定義角色提供程序。

相關問題