当前位置:  开发笔记 > 编程语言 > 正文

ASP.Net Core - 没有API auth错误的重定向

如何解决《ASP.NetCore-没有APIauth错误的重定向》经验,为你挑选了2个好方法。

在我的ASP.NET核心项目中,我得到了一些带有jwt-authorization的API控制器,如下所示:

[Route("api/v1/[controller]")]
public class MyController : Controller
{
  [HttpGet("[action]")]
  [Authorize(Policy = MyPolicy)]
  public JsonResult FetchAll()
  {
  }
}

当访问操作FetchAll()的授权失败时,我想要HttpStatusCode.Forbidden作为响应.相反,Mvc重新路由到帐户/登录?ReturnUrl = [...]

我试图捕获Redirect-Events并返回Forbidden/Unauthorized覆盖Cookie事件无效:

  app.UseIdentity();

  var tokenValidationParameters = new TokenValidationParameters
  {
    ValidateIssuerSigningKey = true,
    IssuerSigningKey = TokenController.DummyKey,
    ValidateIssuer = false,
    ValidateAudience = false,
    ValidateLifetime = true,
    ClockSkew = TimeSpan.FromMinutes(0)
  };
  app.UseJwtBearerAuthentication(new JwtBearerOptions
  {
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    TokenValidationParameters = tokenValidationParameters,
  });

  app.UseCookieAuthentication(new CookieAuthenticationOptions()
  {
    AutomaticAuthenticate = false,
    AutomaticChallenge = false,
    AuthenticationScheme = "BsCookie",
    CookieName = "access_token",
    TicketDataFormat = new CustomJwtDataFormat(SecurityAlgorithms.HmacSha256, tokenValidationParameters),
    Events = new CookieAuthenticationEvents
    {
      OnRedirectToLogin = context =>
      {
        if (context.Request.Path.StartsWithSegments("/api") && context.Response.StatusCode == (int)HttpStatusCode.OK)
          context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
        else
          context.Response.Redirect(context.RedirectUri);
        return Task.FromResult(0);
      },

      OnRedirectToAccessDenied = context =>
      {
        if (context.Request.Path.StartsWithSegments("/api") && context.Response.StatusCode == (int)HttpStatusCode.OK)
          context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
        else
          context.Response.Redirect(context.RedirectUri);
        return Task.FromResult(0);
      }
    },
  });

从不调用这两个事件,并且Visual Studio输出显示将返回fetchall Fails和Account/Login:

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:6460/api/v1/Lehrer/GetAll application/json 
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: Successfully validated the token.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: (null).
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 ().
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: AuthenticationScheme: Bearer was forbidden.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware:Information: AuthenticationScheme: Identity.Application was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Sam.Learning2.Controllers.LehrerController.GetAll (Sam.Learning2) in 49.7114ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 121.6106ms 302 
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:6460/Account/Login?ReturnUrl=%2Fapi%2Fv1%2FLehrer%2FGetAll  

我希望我的API返回401/403而不是重定向到Login - 如果以上代码不起作用,我该如何实现?



1> Tseng..:

更新ASP.NET Core 2.x.

ASP.NET Core 2.0中的授权稍有变化.下面的答案仅对ASP.NET Core 1.x有效.对于ASP.NET Core 2.0,请参阅此答案和此GitHub公告.

ASP.NET Core 1.x

你似乎忘记的是,app.UseIdentity()它还注册了cookie中间件.

var options = app.ApplicationServices.GetRequiredService>().Value;
app.UseCookieAuthentication(options.Cookies.ExternalCookie);
app.UseCookieAuthentication(options.Cookies.TwoFactorRememberMeCookie);
app.UseCookieAuthentication(options.Cookies.TwoFactorUserIdCookie);
app.UseCookieAuthentication(options.Cookies.ApplicationCookie);

并且ASP.NET Core Identity 为cookie()中间件设置了AutomaticChallangeto (参见源代码).因此重定向到.您需要在Identity中禁用此选项.trueApplicationCookie/Account/Login?ReturnUrl

services.AddIdentity(options =>
{
    options.Cookies.ApplicationCookie.AutomaticChallenge = false;
});

如果你真的想拥有Identity的Auth(登录网页)和JWT,你需要根据网址注册中间件.所以ie app.UseIdentity()只注册了非api urls,Jwt中间件只注册了以urls开头的网址/api.

你可以用.MapWhen(docs)做到这一点.

app.MapWhen(context => !context.Request.Path.StartsWith("/api"), branch => 
{
    branch.UseIdentity();
});

现在branch.UseIdentity()只会用于不开头的URL,这些URL /api通常是您/Account/Login需要重定向的MVC视图.



2> akaco..:

我只是使用Barry Dorrans Asp Net 授权工作室

ConfigureServices我只是添加services.AddAuthorization();.

Configure添加此代码:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationScheme = "Cookie",
    LoginPath = new PathString("/Account/Login/"),
    AccessDeniedPath = new PathString("/Account/Forbidden/"),
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    Events = new CookieAuthenticationEvents()
    {
        OnRedirectToLogin = (ctx) =>
        {
            if (ctx.Request.Path.StartsWithSegments("/api") && ctx.Response.StatusCode == 200)
            {
                ctx.Response.StatusCode = 401;
            }
            else
                ctx.Response.Redirect(ctx.RedirectUri);

            return Task.CompletedTask;
        },
        OnRedirectToAccessDenied = (ctx) =>
        {
            if (ctx.Request.Path.StartsWithSegments("/api") && ctx.Response.StatusCode == 200)
            {
                ctx.Response.StatusCode = 403;
            }
            else
            {
                ctx.Response.Redirect(ctx.RedirectUri);
            }
            return Task.CompletedTask;
        }
    }
}

在Mvc重新路由到帐户/登录?ReturnUrl = [...]并在API中,您将获得401或403.

推荐阅读
重庆制造漫画社
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有