2015-08-22 48 views
16

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

UPDATE:

這是不是一個真正的代碼問題,更多的是概念上的問題。

普通MVC網頁檢查默認名爲「.AspNet.ApplicationCookie」的cookie,以確定請求者標識。這個cookie是通過調用ApplicationSignInManager.PasswordSignInAsync生成的。

另一方面,WebAPI調用檢查名爲Authorization的項目的請求標頭,並使用該值確定請求者標識。這是從WebAPI調用返回「/令牌」。

這些是非常不同的值。我的網站需要同時使用MVC頁面 WebAPI調用(以動態更新這些頁面)......並且都需要通過身份驗證才能執行其任務。

我能想到的唯一方法是實際驗證兩次......一次使用WebAPI調用,再次使用登錄帖子。 (請參閱下面的答案)。

這似乎很hacky ...但我不明白授權代碼足以知道是否有更合適的方式來完成此操作。

+0

請告訴你代碼 –

回答

6

實現這一目標有一個授權服務器(一個的WebAPI生成令牌)和令牌消費中間件在你的MVC project.IdentityServer https://github.com/IdentityServer/IdentityServer3 SH最好的方法應該幫忙。不過,我已經這樣做了如下

內置使用智威湯遜與WEB API和ASP.Net身份授權服務器一旦你這樣做,你的webAPIs startup.cs會像這裏http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-and-identity-2/

說明如下

//配置的Web應用程序和智威湯遜的SPA cookie認證,移動應用

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(new CookieAuthenticationOptions()); 

    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類https://github.com/tjoudeh/AspNetIdentity.WebApi/tree/master/AspNetIdentity.WebApi/Providers

編寫消費邏輯(即中間件)的所有其他API(資源服務器),您想使用相同的令牌保護。既然你想消耗你的MVC項目通過的WebAPI生成的令牌,實施授權服務器後,你需要做以下

在你的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控制器時,您收到令牌解序列,並生成訪問令牌

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); 

一個cookie生成計算機密鑰並在您的WebAPI和ASP.Net MVC網站的web.config中添加。

有了這個cookie將被創建,MVC站點和WebAPI中的[Authorize]屬性將遵循這個cookie。

P.S. - 我使用發佈JWT(授權服務器或Auth &資源服務器)的Web API完成了此項工作,併成功地在ASP.Net MVC網站中使用了SPA網站,內置Angular的SPA網站,使用python(資源服務器)構建的安全API,spring (資源服務器),Android應用程序。

0

我和你有類似的情況,但我使用不同的方式進行身份驗證。

我有一個網絡和一個API,這一切都爲內聯網用戶。我不使用用戶的身份來傳遞Web和API。相反,我創建了一個單獨的Web帳戶,並且每次Web都將使用此特殊帳戶連接到api。

因爲我們還需要確保用戶不應該直接連接到API。他們只應該連接到網絡用戶界面。

希望這對你有所幫助。

2

Ugg ...我所要做的就是使用Login.cshtml表單並重寫提交...進行Ajax調用以獲取WebApi不記名令牌...然後執行表單提交以獲取實際MVC cookie。所以,我實際上做了兩個登錄請求......一個用於WebApi令牌,另一個用於MVC cookie。

對我來說這似乎很不好意思......如果有某種方式使用不記名令牌登錄MVC,或者調用WebApi,它會返回一個我可以用於Cookie的cookie正常的MVC頁面請求。

如果有人有更好的方法,我很樂意聽到它。

這是腳本代碼,我加入到Login.cshtml:

$(document).ready(function() { 
     $('form:first').submit(function (e) { 
      e.preventDefault(); 
      var $form = $(this); 
      var formData = $form.serializeObject(); // https://github.com/macek/jquery-serialize-object 
      formData.grant_type = "password"; 
      $.ajax({ 
       type: "POST", 
       url: '@Url.Content("~/Token")', 
       dataType: "json", 
       data: formData, // seems like the data must be in json format 
       success: function (data) { 
        sessionStorage.setItem('token', data.access_token); 
        $form.get(0).submit(); // do the actual page post now 
       }, 
       error: function (textStatus, errorThrown) { 
       } 
      }); 
     }); 
    }); 
0

我假設你正在試圖做的是有通過MVC服務頁面的JavaScript,使得對Web API方法的調用。如果你使用ASP。NET身份來處理身份驗證(看起來您正在進行身份驗證),那麼MVC應該使用可以傳遞給Web API進行身份驗證的OAuth令牌。

下面是一些JavaScript代碼片段,在類似的情況對我的作品:

var token = sessionStorage.getItem('access_token'); 
var headers = {}; 
if (token) { 
    headers.Authorization = 'Bearer ' + token; 
} 
$.ajax({ 
    type: <GET/POSt/...>, 
    url: <your api>, 
    headers: headers 
}).done(function (result, textStatus) { 
+0

你的描述是完全正確的......但問題是如何以及在哪裏獲得access_token,存儲在sessionStorage中,首先......以及在哪裏以及如何獲得用於MVC頁面認證的cookie。 –

+0

訪問令牌由MVC框架存儲在sessionStorage中,我的代碼不必將其存儲在那裏。如果您的代碼沒有發生這種情況,請發佈您如何配置ASP.NET身份/ OAuth。 – DavidS

0

這是你的問題的解決方案。 您可以使用Auth0這裏link

  1. 用戶輸入他們的登錄憑據 服務器驗證憑據是否正確,並返回一個簽名令牌

  2. 此標記存儲客戶端,最常用的本地存儲 - ,但可以存儲在會話存儲或cookie中以及

  3. 對服務器的後續請求將此令牌包含爲 附加的授權標頭或通過以上

  4. 服務器解碼JWT並且如果令牌是有效的處理 請求

  5. 一旦用戶註銷時,該令牌被破壞客戶端,沒有 提到的其他方法 一個與服務器的交互是必要

0

根據您的意見,從我的理解,你有一個場景,其中你通過瀏覽器執行登錄,但也必須調用使用ajax調用web-api方法。

瀏覽器調用是基於會話cookie的。雖然來自瀏覽器的ajax調用會在頭中包含會話cookie,但需要爲web-api提供身份驗證頭以執行驗證。

因此,如果登錄成功,您還必須生成一個基於web-api的令牌,將其設置爲cookie(可通過javascript訪問),然後在進行ajax調用時從Cookie中選取幷包含它作爲'授權'標題中的標題。

相關問題