Asp.net-Web-Api

身份驗證/授權 MVC 5 和 Web API - Katana/Owin

  • April 10, 2015

我在嘗試決定承擔我的項目的路線時遇到問題。

我一直在閱讀 OWIN 規範和 .NET 中的 Katana 實現。我想使用 Katana 路線的原因是因為與 ADFS 和 Token/Cookie 生成相關的 owin 組件。

我有兩個項目,一個用於 MVC 5 網站,一個用於 Web API。將來它們可能位於兩台不同的伺服器上,但現在它們在同一台伺服器上。

我知道我將使用 IIS,因此我不需要調查 Owin 管道。

我的要求是,有些使用者將使用 ADFS 登錄,而其他使用者將使用 Token/Cookie 生成以及角色/成員資格提供程序登錄。根據誰通過身份驗證,我的網頁的某些部分將被公開。網頁工程師是在剃刀中完成的。

有沒有人可以閱讀任何材料來幫助解釋我可以採用的設計流程?或者有人做過類似於我正在經歷的項目,可以添加任何建議?有很多不同的文件描述了我需要的具體事物,但不是全域;就像只談論 WebAPI 和 ADFS,或者 WebAPI 和 windows azure 等。

我的理論是在MVC5網站項目上實現認證/授權,在Web API上進行授權(不知何故兩者之間需要存在通信)。然後我可能會為 ADFS 創建一個項目副本並為令牌/cookie 身份驗證創建另一個副本?或者也許我必須進行 4 種不同類型的身份驗證:2 種用於我對 MVC5 網站和 Web API 進行身份驗證的 adfs,另外 2 種用於令牌/cookie 生成。

任何建議都會有所幫助,因為我對這種技術不是很熟悉。

我可以提供 OWIN 中的 WsFederation 選項很好,但需要 cookie……而且它們是與帶有 cookie 的本地身份驗證不同類型的 cookie。ADFS 2.0/WsFederation 使用 AuthenticationType=“Cookies”,本地身份驗證使用 AuthenticationType=“ApplicationCookie”。據我所知,它們顯然是不相容的。我認為您必須對 ADFS 使用令牌身份驗證,但我認為這需要 2012R2 上的 ADFS 3.0。為此,請使用 OWIN OAuth。

更新:在研究了一段時間後,我想出瞭如何讓這兩種身份驗證類型在同一個 Web 應用程序中和平共存。使用 OWIN,設置兩次呼叫 UseCookieAuthentication,一次啟用新的 WsFederationAuthentication 中間件,再次啟用本地 cookie 身份驗證。這並不直覺,但在幕後,為每個指定不同的身份驗證類型將它們設置為不同的身份驗證“引擎”。這是它在我的 Startup 中的外觀:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
   AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
   LoginPath = new PathString("/Account/Login"),
   Provider = new CookieAuthenticationProvider
       {
           OnResponseSignIn = ctx =>
           {
               ctx.Identity = TransformClaims(ctx, app);
           }
       }
});

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
   Provider = new CookieAuthenticationProvider
   {
       OnResponseSignIn = ctx =>
       {
           ctx.Identity = TransformClaims(ctx, app);
       }
   }
});

app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
{
   Wtrealm = Realm,
   MetadataAddress = Metadata,
   Caption = "Active Directory",
   SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType
});

這成功地允許使用者對本地 SQL 表或 ADFS 2.0 進行身份驗證。TransformClaims 標註允許我規範這兩個提供者之間的聲明,以便它們保持一致。

編輯:這是一個非常基本的 TransformClaims。你可以在其中做很多事情:從你的數據庫中獲取使用者,設置導航聲明,自定義權限,角色集合等等。我剛剛從一個更大的實現中建構了這個精簡版本,所以我沒有執行它,但希望您了解如何利用 OnResponseSignIn 事件。

private static ClaimsIdentity TransformClaims(CookieResponseSignInContext ctx, IAppBuilder app)
{
   var ident = ctx.Identity;

   var claimEmail = ident.Claims.SingleOrDefault(c => c.Type == ClaimTypes.Email);
   var claimName = ident.Claims.SingleOrDefault(c => c.Type == ClaimTypes.Name);

   //normalize my string identifier
   var loginString = (claimEmail != null) ? claimEmail.Value : (claimName != null) ? claimName.Value : null;
   var efctx = ctx.OwinContext.Get<DBEntities>();

   var user = UserBL.GetActiveUserByEmailOrName(efctx, loginString);
   if (user == null)
   {
       //user was auth'd by ADFS but hasn't been auth'd by this app
       ident.AddClaim(new Claim(ClaimTypesCustom.Unauthorized, "true"));
       return ident;
   }

   if (ident.Claims.First().Issuer == "LOCAL AUTHORITY")
   {
       //Local
       //local already has claim type "Name"
       //local didn't have claim type "Email" - adding it
       ident.AddClaim(new Claim(ClaimTypes.Email, user.Email));
   }
   else
   {
       //ADFS
       //ADFS already has claim type "Email"
       //ADFS didn't have claim type "Name" - adding it
       ident.SetClaim(ClaimTypes.Name, user.UserName);
   }

   //now ident has "Name" and "Email", regardless of where it came from
   return ident;
}

引用自:https://stackoverflow.com/questions/22942479