在没有原则的情况下在线程上使用Authorize属性时,Asp.net Core操作不返回401?

Roy*_*mir 6 c# asp.net-core asp.net-core-2.0

我想自己在线程上添加一个原则,而不使用Identity机制,它真的让我想起旧的成员资格/表单身份验证机制.

所以我已成功(成功)创建了一个原则请求:

MyAuthMiddleware.cs

public class MyAuthMiddleware
{
    private readonly RequestDelegate _next;


    public MyAuthMiddleware(RequestDelegate next )
    {
        _next = next;

    }


    public async Task Invoke(HttpContext httpContext)
    {
        var claims = new List<Claim>  
        {  
            new Claim("userId", "22222222")  
        };  
        ClaimsIdentity userIdentity = new ClaimsIdentity(claims ,"MyAuthenticationType");  
        ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);

         httpContext.User = principal;
         await _next(httpContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

配置方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            //app.UseAuthentication(); //removed it. I will set the thread manually
            if (env.IsDevelopment()) app.UseDeveloperExceptionPage();

            app.UseMyAuthMiddleware(); // <---------- Myne

            app.UseMvc();
            app.Run(async context => { await context.Response.WriteAsync("Hello World!"); });
        }
Run Code Online (Sandbox Code Playgroud)

这里是控制器中的动作:(通知授权属性)

    [HttpGet]
    [Route("data")]
    [Authorize]
    public IActionResult GetData()
    {

        var a=User.Claims.First(f => f.Type == "userId");
        return new JsonResult(new List<string> {"a", "b",a.ToString() , User.Identity.AuthenticationType});
    }
Run Code Online (Sandbox Code Playgroud)

好吧让我们尝试调用这个方法,请注意这确实有效:

在此输入图像描述

那问题出在哪里?

请注意,有一个[Authorize]属性.现在让我们删除
线程上的设置原则(删除此行):

//httpContext.User = principal; // line is remarked
Run Code Online (Sandbox Code Playgroud)

但现在我导航到:

http://localhost:5330/api/cities/data
Run Code Online (Sandbox Code Playgroud)

我被重定向到:

http://localhost:5330/Account/Login?ReturnUrl=%2Fapi%2Fcities%2Fdata
Run Code Online (Sandbox Code Playgroud)

但我期待看到未经授权的错误.

我正在接受WebApi的回应.这不是一个网站,而是一个API.

题:

为什么我看不到未经授权的错误?我怎样才能让它出现?

这里的Nb是我的ConfigureServices:

 public void ConfigureServices(IServiceCollection services)
        {
             services.AddAuthentication( CookieAuthenticationDefaults.AuthenticationScheme ) 
                  .AddCookie( CookieAuthenticationDefaults.AuthenticationScheme,  a =>
                  {
                      a.LoginPath = "";
                      a.Cookie.Name = "myCookie";


                  });

            services.AddMvc();
        }
Run Code Online (Sandbox Code Playgroud)

编辑

目前我设法做的是使用OnRedirectionToLogin:

在此输入图像描述

但如果要走的话,那将是非常令人失望的.我期待它像webapi一样.

Kir*_*kin 4

委托的默认实现如下OnRedirectToLogin所示:

public Func<RedirectContext<CookieAuthenticationOptions>, Task> OnRedirectToLogin { get; set; } = context =>
{
    if (IsAjaxRequest(context.Request))
    {
        context.Response.Headers["Location"] = context.RedirectUri;
        context.Response.StatusCode = 401;
    }
    else
    {
        context.Response.Redirect(context.RedirectUri);
    }
    return Task.CompletedTask;
};
Run Code Online (Sandbox Code Playgroud)

从上面的代码可以清楚地看出,发送到客户端的响应取决于 的结果IsAjaxRequest(...),其本身如下所示:

private static bool IsAjaxRequest(HttpRequest request)
{
    return string.Equals(request.Query["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal) ||
        string.Equals(request.Headers["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal);
}
Run Code Online (Sandbox Code Playgroud)

401这意味着如果X-Requested-With请求标头或查询字符串值设置为 ,则响应将是重定向XMLHttpRequest。当您直接从浏览器或从 Fiddler 中访问端点时,不会设置此值,因此响应是 a 302,如观察到的。否则,当在浏览器中使用 XHR 或 Fetch 时,系统会将此值设置为标头,因此401会返回 a。

  • 确认:添加此标头(_默认情况下将由ajax添加_) - 确实返回 401 但仍然带有“Location”响应标头(我必须弄清楚如何删除它) - https://i.imgur .com/FxBELor.jpg。但严格来说,它确实回答了核心问题 (3认同)