ASP.Net Core-API身份验证错误上没有重定向 [英] ASP.Net Core - no redirect on API auth error
问题描述
在我的ASP.NET Core项目中,我得到了一些具有jwt-authorization的API控制器,如下所示:
In my ASP.NET Core project I got a few API-Controllers with jwt-authorization like this:
[Route("api/v1/[controller]")]
public class MyController : Controller
{
[HttpGet("[action]")]
[Authorize(Policy = MyPolicy)]
public JsonResult FetchAll()
{
}
}
访问操作FetchAll()的授权失败时,我需要HttpStatusCode.Forbidden作为响应.相反,Mvc会重新路由到帐户/登录吗?ReturnUrl = [...]
When authorization for accessing the action FetchAll() Fails I want HttpStatusCode.Forbidden as response. Instead Mvc does a reroute to Account/Login?ReturnUrl=[...]
我试图捕获重定向事件并返回禁止/未经授权的覆盖Cookie事件,但无济于事:
I tried to capture the Redirect-Events and return Forbidden/Unauthorized overriding the Cookie Events to no avail:
app.UseIdentity();
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = TokenController.DummyKey,
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(0)
};
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
TokenValidationParameters = tokenValidationParameters,
});
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AutomaticAuthenticate = false,
AutomaticChallenge = false,
AuthenticationScheme = "BsCookie",
CookieName = "access_token",
TicketDataFormat = new CustomJwtDataFormat(SecurityAlgorithms.HmacSha256, tokenValidationParameters),
Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/api") && context.Response.StatusCode == (int)HttpStatusCode.OK)
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
else
context.Response.Redirect(context.RedirectUri);
return Task.FromResult(0);
},
OnRedirectToAccessDenied = context =>
{
if (context.Request.Path.StartsWithSegments("/api") && context.Response.StatusCode == (int)HttpStatusCode.OK)
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
else
context.Response.Redirect(context.RedirectUri);
return Task.FromResult(0);
}
},
});
两个事件都不会调用,Visual Studio输出显示fetchall失败和帐户/登录将返回:
Both Events are never called and the Visual Studio output Shows that fetchall Fails and Account/Login will be returned instead:
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:6460/api/v1/Lehrer/GetAll application/json
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: Successfully validated the token.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: (null).
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: AuthenticationScheme: Bearer was forbidden.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware:Information: AuthenticationScheme: Identity.Application was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Sam.Learning2.Controllers.LehrerController.GetAll (Sam.Learning2) in 49.7114ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 121.6106ms 302
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:6460/Account/Login?ReturnUrl=%2Fapi%2Fv1%2FLehrer%2FGetAll
我希望我的API返回401/403,而不是重定向到Login-在上述代码不起作用时如何实现?
I want my APIs to return 401/403 instead of redirecting to Login - how do I achieve this when above code does not work?
推荐答案
更新ASP.NET Core 2.x
在ASP.NET Core 2.0中,授权发生了一些变化.下面的答案仅对ASP.NET Core 1.x有效.对于ASP.NET Core 2.0,请参考此答案和此您似乎忘记了的是app.UseIdentity()
也是
What you seems to have forgotten is that app.UseIdentity()
also registers the cookie middleware.
var options = app.ApplicationServices.GetRequiredService<IOptions<IdentityOptions>>().Value;
app.UseCookieAuthentication(options.Cookies.ExternalCookie);
app.UseCookieAuthentication(options.Cookies.TwoFactorRememberMeCookie);
app.UseCookieAuthentication(options.Cookies.TwoFactorUserIdCookie);
app.UseCookieAuthentication(options.Cookies.ApplicationCookie);
和ASP.NET Core Identity将cookie(ApplicationCookie
)中间件(true
/fundamentals/middleware#creating-a-middleware-pipeline-with-iapplicationbuilder"rel =" noreferrer>请参阅源文件).因此,重定向到/Account/Login?ReturnUrl
.您需要在身份中禁用此选项.
and the ASP.NET Core Identity sets the AutomaticChallange
to true
for cookie (ApplicationCookie
) middleware (see source). Hence the redirect to /Account/Login?ReturnUrl
. You will need do disable this option in Identity.
services.AddIdentity(options =>
{
options.Cookies.ApplicationCookie.AutomaticChallenge = false;
});
如果您真的希望拥有Identity的Auth(登录到网页)和JWT,则需要根据URL注册中间件.因此,即app.UseIdentity()
仅针对非API网址注册,而Jwt中间件仅针对以/api
开头的网址注册.
If you really want have Identity's Auth (login to web page) and JWT, you'd need to register the middlewares based on the url. So i.e. app.UseIdentity()
is only registered for non-api urls and Jwt middleware is only registered for urls starting with /api
.