防止在asp.net 5(vNext)中对飞行前OPTIONS请求进行基于令牌的授权

本文关键字:请求 于令牌 授权 令牌 OPTIONS asp net vNext 飞行前 | 更新日期: 2023-09-27 18:28:59

我在asp.net 5(RC1)中有一个几乎可以工作的OAuth2实现。我的解决方案基于Mark Hughes在ASP.NET 5(vNext)中给出的基于令牌的身份验证代码,这非常棒。

我的问题是,我的设置使用CORS请求,几乎每个请求前面都有一个OPTIONS请求。尽管我只将Authorize属性应用于GetAll控制器操作/方法,如下所示,但前面的OPTIONS请求也得到了授权。

[Route("api/[controller]")]
public class TextController : Controller
{
    [HttpGet]
    [Authorize("Bearer", Roles = "admin")]
    public IEnumerable<string> GetAll()
    {
        return _repository.GetAll;
    }
    ...
}

startup.cs中的授权服务设置如下:

services.AddAuthorization(auth =>
        {
            auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
                .RequireAuthenticatedUser().Build());
        });

有没有任何方法可以更改授权中间件的行为以跳过OPTIONS请求的授权?

注:

我曾尝试创建自己的授权属性,但由于某种原因,IsAuthenticated的评估结果总是为false,就好像在到达以下代码时还没有进行授权一样:

public class BearerAuthorizationAttribute : Attribute, IAuthorizationFilter
{
    private readonly string Role;
    public BearerAuthorizationAttribute(string Role = null)
    {
        this.Role = Role;
    }
    [Authorize("Bearer")]
    public void OnAuthorization(Microsoft.AspNet.Mvc.Filters.AuthorizationContext context)
    {
        string meth = context.HttpContext.Request.Method;
        if (meth != "OPTIONS")
        {
            if (!context.HttpContext.User.Identity.IsAuthenticated)
            {
                context.Result = new ContentResult() { Content = "Unauthorized", StatusCode = 401 };
                return;
            }
            if (Role != null && !context.HttpContext.User.IsInRole(Role))
            {
                context.Result = new ContentResult() { Content = "Unauthorized, role level insufficient", StatusCode = 401 };
                return;
            }
        }
    }
}

防止在asp.net 5(vNext)中对飞行前OPTIONS请求进行基于令牌的授权

我终于找到了解决问题的方法。在我的Startup.cs中,我使用的是services.AddCors,就像这样:

// Create CORS policies
services.AddCors(options =>
{
    // Define one or more CORS policies
    options.AddPolicy("AllowSpecificOrigin",
        builder =>
        {
            builder.WithOrigins(Configuration.Get<string[]>("AppSettings:AllowedOrigins")) // TODO: revisit and check if this can be more strict and still allow preflight OPTION requests
                        .AllowAnyMethod() 
                        .AllowAnyHeader();
        }
    );
});
// Apply CORS policy globally
services.Configure<MvcOptions>(options =>
{
    options.Filters.Add(new CorsAuthorizationFilterFactory("AllowSpecificOrigin"));
});

事实证明,这只是部分奏效。

对我来说,解决方案是代替app.UseCors,即删除上面的代码并执行以下操作:

app.UseCors(builder =>
{
    builder.WithOrigins(Configuration.Get<string[]>("AppSettings:AllowedOrigins")) // TODO: revisit and check if this can be more strict and still allow preflight OPTION requests
        .AllowAnyMethod()
        .AllowAnyHeader();
});

当使用app.UseCors时,我得到了完全工作的CORS处理,它在OPTIONS请求被授权之前会弹出这些请求。

该解决方案的灵感来源于CORS不适用于具有OWIN身份验证的web api。