2015-08-20 42 views
1

由於我編寫了(當前)我的應用程序服務的實現方式以及它們的配置方式,因此我對MVC應用程序有點pick le依賴注入。MVC 5.2 Cookie登錄OWIN並注入經過身份驗證的用戶信息

我期待通過遵循SOLID原則來分離應用程序的各個層次。

問題是,在這些服務的某些中,構造函數需要IUserContext的一個實例。 IUserContext包含有關登錄用戶的各種信息,並將在幾個不同的層次上傳遞。

public class ProjectDataLoader : DataLoaderBase, IProjectDataLoader 
{ 
    public ProjectDataLoader(IMyDbContext dbContext, IUserContext userContext) 
     : base (dbContext, userContext) 
    { 
    } 
    ... 

    public IEnumerable<ProjectViewModel> Find(string filter = "") 
    { 
     ... 
    } 
} 

而且IUserContext的實現:

public class AspNetUserContext : IUserContext 
{ 
    ... 
} 

我能通過IUserContext對每一個方法調用,但我覺得它屬於在構造函數中。但這不是問題。

當我通過AccountController從登錄頁面登錄時,通過OWIN管道調用MyAppSignInManager.SignInOrTwoFactor。在這一點上我是在會話建立AspNetUserContext的新實例:

HttpContext.Current.Session["UserContext"] = aspNetUserContext; 

現在我有自定義SignInManager實現:

public class MyAppSignInManager : SignInManager<MyAppUser, string> 
{ 
    ... 
} 

我有一個自定義IUserStore實現:

public class MyAppUserStore : IUserPasswordStore<MyAppUser>, 
    IUserStore<MyAppUser> 
{ 
    ... 
} 

上述所有內容都已通過Simple Injector的依賴注入技術與我選擇的容器相連接。

​​

而且也:

public partial class Startup 
{ 
    public void ConfigureAuth(IAppBuilder app, Container container) 
    { 
     app.CreatePerOwinContext(() => container.GetInstance<MyAppUserManager>()); 

     app.UseCookieAuthentication(new CookieAuthenticationOptions 
     { 
      AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
      LoginPath = new PathString(value: "/Account/Login"), 
      Provider = new CookieAuthenticationProvider 
      { 
       OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<MyAppUserManager, MyAppUser>(
        validateInterval: TimeSpan.FromMinutes(value: 30), 
        regenerateIdentity: (manager, user) => 
        { 
         return user.GenerateUserIdentityAsync(manager); 
        }) 
      } 
     }); 
     app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); 
     app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5)); 
     app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie); 
    } 
} 

那麼這些都是在控制器中使用:

public class ProjectController : MyBaseContextController 
{ 
    public ProjectController(IProjectDataLoader loader) 
     : base(context) 
    { 
     ... 
    } 
} 

我最初的問題將是我怎麼能Cookie身份驗證後得到MyAppUser已經發生。也許問這個問題仍然有效。

更好的問題是問我想要完成什麼。基本上我想要的是將IUserContext注入到我的服務中。這需要注入到我的DI容器中註冊的各種服務實現的構造函數中。但是,此實例在用戶登錄/認證之前不可用。

注意:所有的用戶信息都存儲在SQL中,我使用實體框架來訪問所有這些。

因此,如果一旦用戶通過登錄頁面通過MyAppSignInManager.SignInOrTwoFactor方法以及cookie進行身份驗證,我如何才能使我的DINet容器中的AspNetUserContext(IUserContext)實例可用?

注意:我只想從數據庫中獲取用戶信息一次 - 而不是每次調用需要的控制器。

回答

2

「我只想從數據庫中獲取用戶信息一次。」

您應該考慮將所需的用戶數據存儲在聲明中。

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
    LoginPath = new PathString(value: "/Account/Login"), 
    Provider = new CookieAuthenticationProvider 
    { 
     OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<MyAppUserManager, MyAppUser>(
      validateInterval: TimeSpan.FromMinutes(value: 30), 
      regenerateIdentity: (manager, user) => 
      { 
       return user.GenerateUserIdentityAsync(manager); 
      }) 
    } 
}) 

GenerateUserIdentityAsync方法增加了核心身份聲明,但您可以覆蓋這一點,並存儲自定義聲稱您的服務需要。然後,不要將IUserContext傳遞給您的服務,您可以傳入IClaimsIdentity

這意味着您不必一直查詢數據庫以獲取所需的數據。聲明將在代碼中指定的30分鐘間隔後自動更新。

希望這會有所幫助。

+0

這個叫什麼名字?當我通過cookie進行身份驗證時,regenerateIdentity不會被調用。我是否需要做額外的地面工作? – Andez

+0

想我得到你。沒有額外的工作,用戶Guid已經存儲在owin中間件的聲明中。然後,我可以將所有其他用戶數據添加到身份的聲明中。 – Andez

相關問題