简体   繁体   English

使 Web API 身份验证返回 401 而不是重定向到登录页面

[英]Make Web API authentication return 401 instead of redirect to login page

I have Web API with OWIN Authentication in Web MVC.我在 Web MVC 中有带有 OWIN 身份验证的 Web API。 I'm using <authentication> in Web.Config for my Web MVC so it's redirecting to login page.我在 Web.Config 中为我的 Web MVC 使用<authentication> ,因此它重定向到登录页面。

<authentication mode="Forms">
    <forms name="WEB.AUTH" loginUrl="~/login" domain="" protection="All" 
    timeout="43200" path="/" requireSSL="false" slidingExpiration="true" />
</authentication>

I'm using [System.Web.Http.Authorize] attribute to authorize my Web API.我正在使用[System.Web.Http.Authorize]属性来授权我的 Web API。 But somehow, the API redirecting to login page same like my MVC app because of above configuration.但不知何故,由于上述配置,API 重定向到登录页面与我的 MVC 应用程序相同。

what I want to do is keep redirecting function for the Web MVC but returning 401 for Web API.我想要做的是继续为 Web MVC 重定向功能,但为 Web API 返回 401。 How can I achieve this?我怎样才能做到这一点? should I create a custom authorization attribute for Web API?我应该为 Web API 创建自定义授权属性吗?

--EDIT-- - 编辑 -

I found the answer from this post SuppressDefaultHostAuthentication in WebApi.Owin also suppressing authentication outside webapi我在 WebApi 中的SuppressDefaultHostAuthentication 帖子中找到了答案。Owin also suppressing authentication outside webapi

So I just add a few lines into my Startup.cs .所以我只是在我的Startup.cs中添加了几行。 I had all my controllers configured with a "api" prefix route.我的所有控制器都配置了“api”前缀路由。

HttpConfiguration config = new HttpConfiguration();
//..some OWIN configuration
app.Map("/api", inner =>
{
  inner.UseWebApi(config);
});

make sure you put app.Map() after Web Api Configuration lines.确保将app.Map()放在 Web Api 配置行之后。 Otherwise, it will give error to MVC application.否则,它会给 MVC 应用程序带来错误。

In .NET Core I have solved it like this, Startup.cs:在 .NET Core 中,我是这样解决的,Startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.Cookie.SameSite = SameSiteMode.Strict;
                options.Cookie.Name = "AuthCookie";
                options.Events.OnRedirectToAccessDenied = UnAuthorizedResponse;
                options.Events.OnRedirectToLogin = UnAuthorizedResponse;
            })
    ....
    }

    internal static Task UnAuthorizedResponse(RedirectContext<CookieAuthenticationOptions> context)
    {
        context.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
        return Task.CompletedTask;
    }

Create a custom AuthorizeAttribute :创建自定义AuthorizeAttribute

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Unauthorized");
    }
}

If you in the future skip the web.config stuff and use owin to setup your authentication, you could in your Startup.cs do:如果您将来跳过 web.config 内容并使用 owin 设置您的身份验证,您可以在Startup.cs中执行以下操作:

var provider = new CookieAuthenticationProvider();
var originalHandler = provider.OnApplyRedirect;
provider.OnApplyRedirect = context =>
{
    if (!context.Request.Uri.LocalPath.StartsWith(VirtualPathUtility.ToAbsolute("~/api")))
    {
        context.RedirectUri = new Uri(context.RedirectUri).PathAndQuery;
        originalHandler.Invoke(context);
    }
};

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    CookieName = FormsAuthentication.FormsCookieName,
    LoginPath = new PathString("/Account/LogOn"),
    ExpireTimeSpan = TimeSpan.FromMinutes(240),
    Provider = provider
});

This is what worked for me.这对我有用。

Creating a custom attribute:创建自定义属性:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class NoRedirectAuthorizeAttribute : AuthorizeAttribute
{        
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
    }
}

Using the attribute in your controller:在控制器中使用属性:

    [HttpDelete]
    [NoRedirectAuthorizeAttribute(Roles = "Admin")]
    [Route("api/v3/thingstodelete/{id=id}")]
    public IHttpActionResult DeleteThingToDelete(Guid id)
    {
      //delete code
    }

Here are just overriding the HandleUnauthorizedRequest method of the AuthorizeAttribute .这里只是覆盖AuthorizeAttribute的 HandleUnauthorizedRequest 方法。 So, instead of sending a redirect (304) to the login page, we send Forbidden(403) HTTP status code.因此,我们发送 Forbidden(403) HTTP 状态代码,而不是向登录页面发送重定向 (304)。

I struggled with this issue and I came up with a way to only do the redirect if I didn't find the token that I use in the header for my custom manual authorization of my WebApi.我在这个问题上苦苦挣扎,我想出了一种方法,如果我没有找到我在标头中用于我的 WebApi 自定义手动授权的令牌,则只进行重定向。 This is my setup (notice the Provider object and OnApplyRedirect action)这是我的设置(注意 Provider 对象和 OnApplyRedirect 操作)

    app.UseCookieAuthentication(new CookieAuthenticationOptions
   {
     AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
     LoginPath = new PathString("/Account/Login"),
     ExpireTimeSpan = TimeSpan.FromMinutes(30),
     Provider =  new CookieAuthenticationProvider
      {
        OnApplyRedirect = (ctx) => {
            var token = HttpContext.Current.Request.Headers.Get("X-User-Token");
            if (token == null) ctx.Response.Redirect(ctx.RedirectUri);
         }
      }
   });  

by default wep api at first check cookie but for changing from cookie to jwt I use below attribute默认情况下 wep api 首先检查 cookie 但是为了从 cookie 更改为 jwt 我使用下面的属性

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

above contoller上面的控制器

In order to change the way IIS behaves based on a convention defined by URL, you want to branch your OWIN pipeline.为了根据 URL 定义的约定更改 IIS 的行为方式,您需要分支 OWIN 管道。 You can do this by using IApplicationBuilder.Map .您可以使用IApplicationBuilder.Map来执行此操作。 Assuming a static config :假设静态config

public void Configure(IApplicationBuilder app)
{
    ...
    app.Map("/api", HandleWebApiRequests);
    ...
}

private static void HandleWebApiRequests(IApplicationBuilder app)
{
    app.UseWebApi(config);
}

The Map method branches the pipeline to the HandleWebApiRequests method based on an URL that begins with "/api" . Map方法根据以"/api"开头的 URL 将管道分支到HandleWebApiRequests方法。

This should cause 401 errors to behave like they are supposed to and simply return 401 with no redirect.这应该会导致 401 错误表现得像它们应该的那样,并且只是返回 401 而没有重定向。

I needed to configure the StatusCodePage middleware to avoid redirection我需要配置 StatusCodePage 中间件以避免重定向

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ...
    app.UseStatusCodePages();
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使Microsoft.AspNetCore.Authorization.AuthorizeAttribute返回401,而不是重定向到登录页面 - Make Microsoft.AspNetCore.Authorization.AuthorizeAttribute return 401, instead of redirecting to login page API 不返回 401 而是返回身份登录页面 - API not returning 401 instead returning Identity Login page 在表单身份验证应用中从Web API返回401消息 - Return 401 message from web api in forms authentication app C# .NET Core Web API,抛出 AuthorizationException,客户端得到 500。如何让它返回 401? - C# .NET Core Web API, throwing an AuthorizationException, client gets a 500. How do I make it return a 401 instead? 为什么ASP.NET Identity返回401而不是重定向到登录页面? - Why ASP.NET Identity returns 401 instead redirect to login page? Web API 2承载在IIS上时返回401,而将身份验证设置为匿名时返回200 - Web API 2 returns 401 when hosted on IIS and return 200 when set authentication to anonymous 从Web-Api重定向到Login.aspx页面 - Redirect to Login.aspx Page from Web-Api 带有401状态的api返回登录页面 - Api with 401 status returning login page forms身份验证中转移而不是重定向登录 - Transfer instead of redirect to login in forms authentication 在Web API中使用基本身份验证登录 - Login with Basic Authentication in web api
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM