Asp.net核心动作没有return401在线程上使用Authorize属性时没有原则?
Asp.net Core action does not return 401 when using Authorize attribute on a thread without a principle?
我想自己在线程上添加一个原则,没有使用身份机制这真的让我想起了旧的membership/forms身份验证机制。
所以我已经(成功地)创建了一个请求,其原则是:
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);
}
}
配置方法:
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!"); });
}
这是控制器中的操作:(通知授权属性)
[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});
}
好的,让我们尝试调用这个方法,请注意这个确实有效:
那么问题出在哪里呢?
请注意有一个 [Authorize]
属性。现在让我们删除
线程设置原则(去掉这一行):
//httpContext.User = principal; // line is remarked
但是现在当我导航到:
http://localhost:5330/api/cities/data
我被重定向到:
http://localhost:5330/Account/Login?ReturnUrl=%2Fapi%2Fcities%2Fdata
但我希望看到未经授权的错误。
我在寻找类似的 WebApi 响应。这不是网站,而是 API.
问题:
为什么我没有看到未经授权的错误?我怎样才能让它出现?
Nb 这是我的配置服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication( CookieAuthenticationDefaults.AuthenticationScheme )
.AddCookie( CookieAuthenticationDefaults.AuthenticationScheme, a =>
{
a.LoginPath = "";
a.Cookie.Name = "myCookie";
});
services.AddMvc();
}
编辑
目前我设法做的是使用 OnRedirectionToLogin :
但如果真的那样的话,那将是非常令人失望的。我希望它像 webapi。
OnRedirectToLogin
委托的默认实现类似于 this:
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;
};
从上面的代码可以清楚地看出,发送到客户端的响应取决于 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);
}
这意味着如果 X-Requested-With
请求 header 或 query-string 值设置为 XMLHttpRequest
,则响应将是 401
重定向。当您直接从浏览器或从内部访问您的端点时Fiddler,此值未设置,因此响应为 302
,如观察到的。否则,当在浏览器中使用 XHR 或 Fetch 时,此值会为您设置为 header,因此会返回 401
。
我想自己在线程上添加一个原则,没有使用身份机制这真的让我想起了旧的membership/forms身份验证机制。
所以我已经(成功地)创建了一个请求,其原则是:
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);
}
}
配置方法:
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!"); });
}
这是控制器中的操作:(通知授权属性)
[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});
}
好的,让我们尝试调用这个方法,请注意这个确实有效:
那么问题出在哪里呢?
请注意有一个 [Authorize]
属性。现在让我们删除
线程设置原则(去掉这一行):
//httpContext.User = principal; // line is remarked
但是现在当我导航到:
http://localhost:5330/api/cities/data
我被重定向到:
http://localhost:5330/Account/Login?ReturnUrl=%2Fapi%2Fcities%2Fdata
但我希望看到未经授权的错误。
我在寻找类似的 WebApi 响应。这不是网站,而是 API.
问题:
为什么我没有看到未经授权的错误?我怎样才能让它出现?
Nb 这是我的配置服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication( CookieAuthenticationDefaults.AuthenticationScheme )
.AddCookie( CookieAuthenticationDefaults.AuthenticationScheme, a =>
{
a.LoginPath = "";
a.Cookie.Name = "myCookie";
});
services.AddMvc();
}
编辑
目前我设法做的是使用 OnRedirectionToLogin :
但如果真的那样的话,那将是非常令人失望的。我希望它像 webapi。
OnRedirectToLogin
委托的默认实现类似于 this:
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;
};
从上面的代码可以清楚地看出,发送到客户端的响应取决于 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);
}
这意味着如果 X-Requested-With
请求 header 或 query-string 值设置为 XMLHttpRequest
,则响应将是 401
重定向。当您直接从浏览器或从内部访问您的端点时Fiddler,此值未设置,因此响应为 302
,如观察到的。否则,当在浏览器中使用 XHR 或 Fetch 时,此值会为您设置为 header,因此会返回 401
。