1

我使用使用實體框架的第三方認證新標識框架ASP MVC 5個網站,因爲它涉及開箱。在用戶我有一個記錄,他們有3個索賠(標準名稱的NameIdentifier和認證供應商,似乎被默認ClaimsIdentityFactory提供)。ASP.NET身份不加載任何索賠

當用戶執行某些操作我再添加使用此爲他們的索賠:

userManager.AddClaim(userId, new Claim(claimType,claimValue)); 

如果我期待在AspNetUserClaims表分貝的話,我看我的新要求一行。大。

然而,當我的用戶則訪問其他頁面,我檢查這個新的要求,但我從來沒有發現它。

我認爲我最初的問題是,登錄用戶從未更新其cookie以包含新索賠,因此我登出他們認爲當他們在框架中登錄時會讀取索賠並創建新索賠用戶,然後他們會在cookie中。但是,即使當我的用戶再次登錄他們沒有索賠時,我也一定會錯過一些東西。

事實上,如果我登錄DB活動時,這條線是所謂的ExternalLoginCallback:

// Sign in the user with this external login provider if the user already has a login 
ApplicationUser user = await UserManager.FindAsync(loginInfo.Login); 

什麼,我得到的是這樣的:

iisexpress.exe' (CLR v4.0.30319: /LM/W3SVC/2/ROOT-2-130416316906840516): Loaded 

'EntityFrameworkDynamicProxies-Microsoft.AspNet.Identity.EntityFramework'. 
SELECT TOP (1) 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Name] AS [Name] 
    FROM [dbo].[AspNetRoles] AS [Extent1] 
    WHERE (((UPPER([Extent1].[Name])) = (UPPER(@p__linq__0))) AND (NOT ((UPPER([Extent1].[Name]) IS NULL) OR (UPPER(@p__linq__0) IS NULL)))) OR ((UPPER([Extent1].[Name]) IS NULL) AND (UPPER(@p__linq__0) IS NULL)) 


-- p__linq__0: 'TeamManagement' (Type = String, Size = -1) 

-- Executing at 10/04/2014 20:28:29 +01:00 

-- Completed in 2 ms with result: GlimpseDbDataReader 



'iisexpress.exe' (CLR v4.0.30319: /LM/W3SVC/2/ROOT-2-130416316906840516): Loaded 'EntityFrameworkDynamicProxies-Haccapp.Model'. 
SELECT 
    [Extent1].[Discriminator] AS [Discriminator], 
    [Extent1].[Id] AS [Id], 
    [Extent1].[UserName] AS [UserName], 
    [Extent1].[PasswordHash] AS [PasswordHash], 
    [Extent1].[SecurityStamp] AS [SecurityStamp], 
    [Extent1].[PreferredEmailAddress] AS [PreferredEmailAddress] 
    FROM [dbo].[AspNetUsers] AS [Extent1] 
    WHERE ([Extent1].[Discriminator] IN (N'ApplicationUser',N'IdentityUser')) AND ([Extent1].[Id] = @p0) 


-- p0: 'SiteOwner' (Type = String, Size = -1) 

-- Executing asynchronously at 10/04/2014 20:28:29 +01:00 

GlimpseDbCommand.TimerStrategy is null 
-- Completed in 6 ms with result: GlimpseDbDataReader 



SELECT 
    [Limit1].[Discriminator] AS [Discriminator], 
    [Limit1].[Id] AS [Id], 
    [Limit1].[UserName] AS [UserName], 
    [Limit1].[PasswordHash] AS [PasswordHash], 
    [Limit1].[SecurityStamp] AS [SecurityStamp], 
    [Limit1].[PreferredEmailAddress] AS [PreferredEmailAddress] 
    FROM (SELECT TOP (1) 
     [Extent2].[Id] AS [Id], 
     [Extent2].[UserName] AS [UserName], 
     [Extent2].[PasswordHash] AS [PasswordHash], 
     [Extent2].[SecurityStamp] AS [SecurityStamp], 
     [Extent2].[PreferredEmailAddress] AS [PreferredEmailAddress], 
     [Extent2].[Discriminator] AS [Discriminator] 
     FROM [dbo].[AspNetUserLogins] AS [Extent1] 
     LEFT OUTER JOIN [dbo].[AspNetUsers] AS [Extent2] ON ([Extent2].[Discriminator] IN (N'ApplicationUser',N'IdentityUser')) AND ([Extent1].[UserId] = [Extent2].[Id]) 
     WHERE ([Extent1].[LoginProvider] = @p__linq__0) AND (@p__linq__0 IS NOT NULL) AND ([Extent1].[ProviderKey] = @p__linq__1) AND (@p__linq__1 IS NOT NULL) 
    ) AS [Limit1] 


-- p__linq__0: 'Google' (Type = String, Size = -1) 

-- p__linq__1: 'https://www.google.com/accounts/o8/id?id=some_account_id' (Type = String, Size = -1) 

-- Executing asynchronously at 10/04/2014 20:28:29 +01:00 

包含什麼,它試圖在數據庫中查詢聲稱所有,實際上我返回的用戶有0個索賠。

的代碼,然後繼續這樣做:

ClaimsIdentity identity = await UserManager.CreateIdentityAsync(user, defaultAuthenticationTypes.ApplicationCookie); 
AuthenticationManager.SignIn(new AuthenticationProperties {IsPersistent = isPersistent}, identity); 

,然後身份有3個索賠。

什麼我必須做的,以使從當我加載我的用戶數據庫加載索賠?一旦我做什麼,我需要做的,以確保任何新的權利要求我的用戶使用該網站的用戶使用網站的更新過程中累積?

我覺得我必須在這裏失去了一些東西根本。

編輯

所以我打更多與此一點,已經結束了實施我自己ClaimsIdentityFactory像這樣:

public class FullyLoadingClaimsIdentityFactory : ClaimsIdentityFactory<ApplicationUser> 
{ 
    private readonly ApplicationDb db; 

    public FullyLoadingClaimsIdentityFactory(ApplicationDb db) 
    { 
     this.db = db; 
    } 

    public override async Task<ClaimsIdentity> CreateAsync(UserManager<ApplicationUser> manager, ApplicationUser user, string authenticationType) 
    { 
     var currentClaims = db.UserClaims.Where(x => x.User.Id == user.Id).ToList(); 
     var claimsIdentity = await base.CreateAsync(manager, user, authenticationType); 
     claimsIdentity.AddClaims(currentClaims.Select(c=>new Claim(c.ClaimType,c.ClaimValue))); 
     return claimsIdentity; 
    } 
} 

這明確現在查詢數據庫加載用戶索賠。我有一個屬性添加到我的課,從IdentityDbContext得出這樣我就可以暴露框架IdentityUserClaim對象:

public IDbSet<IdentityUserClaim> UserClaims { get; set; } 

,現在當我看我的currentClaims它們正確地包含有在礦井表中的索賠。歡呼!

除了當我隨後致電:

var claimsIdentity = await base.CreateAsync(manager, user, authenticationType); 

它還加載我的權利,它不會加載之前。

其實

如果我改成這樣:

var claimsIdentity = await base.CreateAsync(manager, user, authenticationType); 
Trace.WriteLine(claimsIdentity.Claims.Count()); <-- traces 3 
var currentClaims = db.UserClaims.Where(x => x.User.Id == user.Id).ToList(); 
claimsIdentity = await base.CreateAsync(manager, user, authenticationType); 
Trace.WriteLine(claimsIdentity.Claims.Count()); <-- traces 6! 

然後我沒有得到在DB的權利(其中有3)加載,當我第一次創建claimsIdentity但我創造了第二次在手動查詢數據庫之後,身份驗證信息就在那裏。

爲什麼會這樣?我現在感覺像它的EF相關,但不知道爲什麼...

+0

我不確定,但嘗試查看http://msdn.microsoft.com/en-us/library/hh291061(v=vs.110).aspx和http://brockallen.com/2012/07/08/mvc-4-antiforgerytoken-and-claims/ –

+0

@ClarkKent謝謝,但這些似乎都在討論以WIF爲主的較早的實現。它看起來像我需要實現我自己的ClaimsIdentityFactory並手動從UserManager中加載聲明,但感覺各種各樣或錯誤。 –

回答

2

是的,這是一個錯誤,如果您升級到2.0版應該修復。基本上你想確保LazyLoading已啓用,更多信息here

+0

謝謝。我生命中的3個小時我不會回來。但至少現在只有3 :-)。 –