Asp.net-Mvc

將身份驗證同時用於 MVC 頁面和 Web API 頁面?

  • August 22, 2015

我有一個 MVC 5 Web 應用程序,可以使用 Login.cshtml 頁面登錄並獲取 cookie,並且登錄工作正常。但是,我想使用 Web API 登錄,然後(也許)設置一個 cookie,以便我登錄我的 MVC 頁面……(或使用 MVC 登錄然後訪問 Web API)但是web api返回一個不記名令牌而不是cookie令牌……所以這不起作用。有沒有一種方法可以為我的 MVC 頁面和我的 Web API 頁面結合使用身份驗證?

更新:

這不是真正的程式碼問題,更多的是概念問題。

普通的 MVC 網頁會檢查一個名為“.AspNet.ApplicationCookie”的 cookie,以確定請求者的身份。此 cookie 是通過呼叫 ApplicationSignInManager.PasswordSignInAsync 生成的。

另一方面,WebAPI 呼叫檢查名為 Authorization… 的項目的請求標頭,並使用該值來確定請求者的身份。這是從對“/Token”的 WebAPI 呼叫返回的。

這些是非常不同的價值觀。我的網站需要同時使用 MVC 頁面WebAPI 呼叫(以動態更新這些頁面)……並且兩者都需要經過身份驗證才能執行它們的任務。

我能想到的唯一方法是實際進行兩次身份驗證……一次是使用 WebAPI 呼叫,另一次是使用登錄文章。(見下面我的答案)。

這似乎很hacky……但我對授權程式碼的了解不夠,無法知道是否有更合適的方法來完成此操作。

實現這一點的最佳方法是在您的 MVC 項目中擁有一個授權伺服器(一個生成令牌的 Web API)和令牌消費中間件。IdentityServer應該會有所幫助。但是我已經這樣做了:

我使用 JWT 和 Web API 和 ASP.Net Identity 建構了一個授權伺服器,如此所述。

完成此操作後,您的 Web APIstartup.cs將如下所示:

// Configures cookie auth for web apps and JWT for SPA,Mobile apps
private void ConfigureOAuthTokenGeneration(IAppBuilder app)
{
   // Configure the db context, user manager and role manager to use a single instance per request
   app.CreatePerOwinContext(ApplicationDbContext.Create);
   app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
   app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);

   // Cookie for old school MVC application
   var cookieOptions = new CookieAuthenticationOptions
   {
       AuthenticationMode = AuthenticationMode.Active,
       CookieHttpOnly = true, // JavaScript should use the Bearer
       AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,                
       LoginPath = new PathString("/api/Account/Login"),
       CookieName = "AuthCookie"
   };
   // Plugin the OAuth bearer JSON Web Token tokens generation and Consumption will be here
   app.UseCookieAuthentication(cookieOptions);

   OAuthServerOptions = new OAuthAuthorizationServerOptions()
   {
       //For Dev enviroment only (on production should be AllowInsecureHttp = false)
       AllowInsecureHttp = true,
       TokenEndpointPath = new PathString("/oauth/token"),
       AccessTokenExpireTimeSpan = TimeSpan.FromDays(30),
       Provider = new CustomOAuthProvider(),                
       AccessTokenFormat = new CustomJwtFormat(ConfigurationManager.AppSettings["JWTPath"])
   };

   // OAuth 2.0 Bearer Access Token Generation
   app.UseOAuthAuthorizationServer(OAuthServerOptions);
}

你可以在這裡CustomOAuthProvider找到和CustomJwtFormat類。

我在我想要使用相同令牌保護的所有其他 API(資源伺服器)中編寫了一個消費邏輯(即中間件)。由於您要在 MVC 項目中使用 Web API 生成的令牌,因此在實現授權伺服器後,您需要執行以下操作:

在您的 MVC 應用程序中,將其添加到startup.cs

public void Configuration(IAppBuilder app)
{
       ConfigureOAuthTokenConsumption(app);
}

private void ConfigureOAuthTokenConsumption(IAppBuilder app)
{
   var issuer = ConfigurationManager.AppSettings["AuthIssuer"];
   string audienceid = ConfigurationManager.AppSettings["AudienceId"];
   byte[] audiencesecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["AudienceSecret"]);

   app.UseCookieAuthentication(new CookieAuthenticationOptions { CookieName = "AuthCookie" , AuthenticationType=DefaultAuthenticationTypes.ApplicationCookie });

   //// Api controllers with an [Authorize] attribute will be validated with JWT
   app.UseJwtBearerAuthentication(
       new JwtBearerAuthenticationOptions
       {
           AuthenticationMode = AuthenticationMode.Passive,
           AuthenticationType = "JWT",
           AllowedAudiences = new[] { audienceid },
           IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
           {
               new SymmetricKeyIssuerSecurityTokenProvider(issuer, audiencesecret)                           
           }

       });
}

在您的 MVC 控制器中,當您收到令牌時,將其反序列化並從訪問令牌生成 cookie:

AccessClaims claimsToken = new AccessClaims();
claimsToken = JsonConvert.DeserializeObject<AccessClaims>(response.Content);
claimsToken.Cookie = response.Cookies[0].Value;               
Request.Headers.Add("Authorization", "bearer " + claimsToken.access_token);
var ctx = Request.GetOwinContext();
var authenticateResult = await ctx.Authentication.AuthenticateAsync("JWT");
ctx.Authentication.SignOut("JWT");
var applicationCookieIdentity = new ClaimsIdentity(authenticateResult.Identity.Claims, DefaultAuthenticationTypes.ApplicationCookie);
ctx.Authentication.SignIn(applicationCookieIdentity);

生成機器密鑰並將其添加到web.config您的 Web API 和 ASP.Net MVC 站點中。

這樣,將創建一個 cookie,並且[Authorize]MVC 站點和 Web API 中的屬性將遵循此 cookie。

PS我已經通過發布JWT(授權伺服器或身份驗證和資源伺服器)的Web API做到了這一點,並且能夠在ASP.Net MVC網站、Angular內置的SPA站點、python內置的安全API(資源伺服器)中使用它, spring(資源伺服器)和一個 Android 應用程序。

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