簡體   English   中英

Asp.net core 2.0+ - 多種認證方案(Cookie / Bearer)

[英]Asp.net core 2.0+ - Multiple Authentication Schemes (Cookie / Bearer)

我一直在努力使多個身份驗證方案在 Asp.net 核心 2.1 中正常工作。

我使用帶有隱式流和 OpenIdConnect 作為協議的 Identity Server。

當僅使用其中一種方案(例如 Cookie 或 Bearer)授權操作或控制器時,該功能可以正常工作。

例子:

  [Authorize(AuthenticationSchemes = "Cookies")]
  [Route("Cookies")]
  public class BearerAndCookiesController : Controller {

但是,如果我在 Authorize 屬性上指定了兩種方案,那么它會部分失敗。 Bearer 正常工作,但是當我嘗試在瀏覽器中查看頁面時,它會嘗試重定向到本地登錄頁面 ( http://localhost/Account/Login )。

當我檢查 Identity Server 的調試日志時,沒有返回任何內容,這是有道理的,因為它沒有嘗試聯系管理局。 但是,當我查看測試 MVC 站點的調試日志時,Bearer 和 Cookie 方案都受到挑戰:

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:5002/cookies  
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Get", controller = "BearerAndCookies"}. Executing action MvcClient.Controllers.BearerAndCookiesController.Get (MvcClient)
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes (Bearer, Cookies).
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AuthenticationScheme: Bearer was challenged.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action MvcClient.Controllers.BearerAndCookiesController.Get (MvcClient) in 68.1922ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 93.2016ms 302 
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:5002/Account/Login?ReturnUrl=%2Fcookies  
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 30.2532ms 404 
Failed to load resource: the server responded with a status of 404 (Not Found) [http://localhost:5002/Account/Login?ReturnUrl=%2Fcookies]

有誰知道為什么這不起作用? 我要人喝啤酒! 上周它一直在追捕我。

https://docs.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-2.2&tabs=aspnetcore2x

這是我的 Startup.cs 配置:

   public void ConfigureServices(IServiceCollection services) {

      services.AddMvc();

      JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

      services.AddAuthentication(options => {
        options.DefaultScheme = "Cookies";
        options.DefaultChallengeScheme = "oidc";
      })
      .AddJwtBearer(options => {
        options.Authority = "http://localhost:5000";
        options.Audience = "myApi";
        options.RequireHttpsMetadata = false;
      })
      .AddCookie("Cookies")
      .AddOpenIdConnect("oidc", options => {
        options.Authority = "http://localhost:5000";
        options.RequireHttpsMetadata = false;

        options.ClientId = "myApi";
        options.SaveTokens = true;
      });
    }
  [Authorize(AuthenticationSchemes = AuthSchemes)]
  [Route("Cookies")]
  public class BearerAndCookiesController : Controller {

    private const string AuthSchemes =
      JwtBearerDefaults.AuthenticationScheme + "," +
      CookieAuthenticationDefaults.AuthenticationScheme;

我想更好地解釋這個答案:

  1. 在我添加了兩個方案之后,我不得不移動services.AddAuthorization 這可確保正確注冊兩個方案。
 JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

      services.AddAuthentication(options => {
        options.DefaultScheme = "Cookies";
        options.DefaultChallengeScheme = "oidc";
      })
        .AddCookie("Cookies")
        .AddOpenIdConnect("oidc", options => {
          options.SignInScheme = "Cookies";
          options.Authority = "http://localhost:5000";
          options.RequireHttpsMetadata = false;
          options.ClientId = "myApi";
          options.SaveTokens = true;
        }).AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, options => {
          options.Authority = "http://localhost:5000";
          options.ApiName = "myApi";
          options.RequireHttpsMetadata = false;
        });

      services.AddAuthorization(options => {
      ...
      });
  1. 然后我沒有將授權方案指定為控制器操作授權標記的一部分,而是在使用services.AddAuthorization時使用了全局策略
services.AddAuthorization(options =>
{
    var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
        CookieAuthenticationDefaults.AuthenticationScheme,
        JwtBearerDefaults.AuthenticationScheme);
    defaultAuthorizationPolicyBuilder =
        defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
    options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
  1. 當我導航到 API 的任何部分時,它不會重定向到登錄屏幕。 我注意到,如果您首先通過導航到 Identity Server 登錄,然后返回該頁面,它實際上會像往常一樣對您進行身份驗證。 所以我已經加入了一點點黑客的感覺。 重要的是,這直接進入app.UseAuthentication 下
  app.UseAuthentication();
      app.Use(async (context, next) => {
        await next();
        var bearerAuth = context.Request.Headers["Authorization"]
                           .FirstOrDefault()?.StartsWith("Bearer ") ?? false;
        if (context.Response.StatusCode == 401
            && !context.User.Identity.IsAuthenticated
            && !bearerAuth) {
          await context.ChallengeAsync("oidc");
        }
      });

鮑勃是你的叔叔……感謝這篇文章的幫助!! oipapio.com/question-1510997

暫無
暫無

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

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