將身份驗證同時用於 MVC 頁面和 Web API 頁面?
我有一個 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 API
startup.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 應用程序。