簡體   English   中英

JWT 和 Windows 身份驗證的 ASP.Net Core 2.0 混合身份驗證不接受憑據

[英]ASP.Net Core 2.0 mixed authentication of JWT and Windows Authentication doesn't accept credentials

我在 asp.net core 2.0 中創建了 API,我在其中使用了混合模式身份驗證。 對於一些控制器 JWT 和一些使用 Windows 身份驗證。

我對使用 JWT 授權的控制器沒有問題。 但是對於我想使用 Windows 身份驗證的控制器,我會無限期地提示 chrome 的用戶名和密碼對話框。

這是我想使用 Windows 身份驗證而不是 JWT 的示例控制器代碼。

[Route("api/[controller]")]
[Authorize(AuthenticationSchemes = "Windows")]
public class TestController : Controller
{
    [HttpPost("processUpload")]
    public async Task<IActionResult> ProcessUploadAsync(UploadFileModel uploadFileModel)
    {

    }
}

我的配置服務代碼

public void ConfigureServices(IServiceCollection services)
{
     services.AddAuthentication(options =>
     {
        options.DefaultAuthenticateScheme = IISDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
     })
     .AddJwtBearer("Bearer", options =>
     {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = false,       
            ValidateIssuer = false,  
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("blahblahKey")),
            ValidateLifetime = true, //validate the expiration and not before values in the token
            ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date
        };
     });

     // let only my api users to be able to call 
     services.AddAuthorization(auth =>
     {
        auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
            .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
            .RequireClaim(ClaimTypes.Name, "MyApiUser").Build());
     });

     services.AddMvc();
}

我的配置方法。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseCors("CorsPolicy");

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseAuthentication(); //needs to be up in the pipeline, before MVC
    app.UseMvc();
}

感謝您對此的建議和幫助。

更新:到目前為止,我一直在 chrome 上調試我的代碼。 但是當我使用 IE 11 時,上面的代碼運行沒有任何問題。

這可能是預檢問題的 chrome 的 CORS 問題嗎?

謝謝

您需要確保,你設定Authorization: Bearer <JWT_token> HTTP標頭,當您嘗試使用Windows驗證。 這里的關鍵點是“Windows Auth”的實際工作方式。 例如,讓我們看看它是如何與瀏覽器一起工作的。

我們稱之為“正常流程”:

  1. 您在瀏覽器中導航到http://example.com/api/resource
  2. 您的瀏覽器向http://example.com/api/resource發送一個 HTTP GET 請求,目前沒有任何Authorization HTTP 標頭(匿名請求);
  3. Web 服務器(或 WebAPI 本身)收到請求,發現沒有Authorization標頭並以401 Not Authorized狀態碼響應WWW-Authenticate: NTLM,Negotiate HTTP Header setted ( “走開,沒有匿名訪問。只有歡迎使用‘NTLM’或‘Negotiate’!” );
  4. 瀏覽器收到401響應,發現請求是匿名的,查看WWW-Authenticate標頭並立即重復請求,現在使用Authorization: NTLM <NTLM_token> HTTP 標頭( “好吧, Authorization: NTLM <NTLM_token> ,Web 服務器先生!這是我的NTLM 令牌。” );
  5. 服務器收到第二個請求,在Authorization標頭中找到 NTLM 令牌,驗證它並執行請求( “好的,你可以通過。這是你的資源。” )。

當您最初將Authorization標頭設置為某個值時,情況會有所不同:

  1. 您的 JS 需要具有 JWT 授權的http://example.com/api/resource
  2. 你的瀏覽器向http://example.com/api/resource發送一個 HTTP GET 請求,並帶有Authorization: Bearer <JWT_token> HTTP Header 現在;
  3. Web 服務器(或 WebAPI 本身)收到請求,發現存在帶有“Bearer”身份驗證方案的Authorization標頭,並再次以401 Not Authorized狀態碼與WWW-Authenticate: NTLM,Negotiate HTTP Header seted ( “Go away ,我們不知道這個'承載'家伙是誰,但我們不喜歡他們。只歡迎'NTLM'或'談判'家伙!” );
  4. 瀏覽器收到401響應,找出該請求批准,並決定此令牌是壞的。 但是,當您實際設置Authorization標頭時,這意味着您實際上擁有一些憑據。 因此,它會通過此對話框向您詢問此憑據。

謝謝@ vasily.sib。 你是對的我的JWTInterceptor正在向標題中添加JWTToken。 當我評論它並測試它有效。 感謝大家為我節省了2天的痛苦,找出問題所在。 你是冠軍。

我只是有同樣的需求。 我還沒有在 IIS 上運行東西,只有 Kestrel,但我設法調整了 Microsoft 自己的說明,以使用 JWT 和 Windows 身份驗證獲得每個控制器/控制器方法的身份驗證。

我所做的只是修改 Startup.cs/ConfigureServices 從

services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
    x.RequireHttpsMetadata = false; // should be set to true in production
    x.SaveToken = true;
    x.TokenValidationParameters = generateTokenValidationParameters();
});

對此

services.AddAuthentication()
.AddNegotiate()
.AddJwtBearer(x => 
{
    x.RequireHttpsMetadata = false; // should be set to true in production
    x.SaveToken = true;
    x.TokenValidationParameters = generateTokenValidationParameters();
});

因此,基本上,刪除了默認身份驗證和質詢方案,使用我預先存在的 JWT 配置添加了協商(Windows 身份驗證)和 JwtBearer。

在控制器中,我通過添加此授權標頭啟用了 Windows 身份驗證

[Authorize(AuthenticationSchemes = NegotiateDefaults.AuthenticationScheme)]

同樣,我用這個替換了我以前執行 JWD 的現有授權標頭(假設它是默認的身份驗證/挑戰方案)

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

我的應用程序將由 Kestrel 托管,因此 IIS 不會成為問題,但無論如何我接下來會嘗試。

@edit:我現在也掌握了 IIS Express。 通過 VS 的 IIS Express 設置(項目屬性、調試選項卡)啟用 Windows 身份驗證,然后通過將其添加到 Startup.ConfigureServices(在 AddAuthentication 之后)確保 IIS 不會對進出處理托管執行自動身份驗證。

//disable automatic authentication for in-process hosting
services.Configure<IISServerOptions>(options => 
{
    options.AutomaticAuthentication = false;
});

//disable automatic authentication for out-of-process hosting
services.Configure<IISOptions>(options => 
{
    options.AutomaticAuthentication = false;
});

然后我將我的測試控制器更改為具有以下授權標頭的方法

[Authorize(AuthenticationSchemes = IISDefaults.AuthenticationScheme)]

當我使用信任 URL 的瀏覽器訪問該方法時,我被允許進入並且 User.Identity 是我的 Windows 身份。

現在看看這是否也適用於實際的 IIS。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM