首页 文章

防止asp.net 5中的预检OPTIONS请求的基于令牌的授权(vNext)

提问于
浏览
0

我在asp.net 5(RC1)中有一个几乎可以实现的OAuth2 . 我的解决方案基于Mark Hughes在Token Based Authentication in 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;
            }
        }

    }
}

1 回答

  • 1

    我终于想出了如何解决我的问题 . 在我的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"));
    });
    

    事实证明,这只能部分地发挥作用 .

    The solution 对我来说是代替 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 is not working in web api with OWIN authentication .

相关问题