使用ASP.NET MVC 5,我想为不同的场景返回适当的HTTP状态代码(401用户未经过身份验证,403当用户无权使用某些资源时等),然后在jQuery中处理它们。
但问题是,当我尝试返回401时,它总是返回“200:OK”。 MVC 5 RC1给出了“302:Found”而不是401,所以我可以使用一种解决方法(HttpStatusCodeResult(401) returns "302 Found")。 但是现在我从MVC 5 RC1转移到了MVC 5,这种行为发生了变化。现在它总是“200:OK”。所以我的解决方法毫无用处,当然我不能用其他任何东西替换200。
public ActionResult My()
{
if (User.Identity.IsAuthenticated == false)
{
return new HttpStatusCodeResult(401, "User is not authenticated.");
// Returns "200: OK"
}
// ... other code ...
}
如何解决这个问题?
答案 0 :(得分:4)
MVC 5+ Pipeline修改了401响应代码。
选项1使用.net 4.5
您可以将HttpContext.Response.SuppressFormsAuthenticationRedirect
设置为true。
e.g。在您的自定义AuthoriseAttribute.cs
中 protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new JsonResult
{
Data = "_Logon_",
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
}
选项2.如果不使用.net 4.5
public class SuppressFormsAuthenticationRedirectModule : IHttpModule
{
private static readonly object SuppressAuthenticationKey = new object();
public static void Register()
{
DynamicModuleUtility.RegisterModule(
typeof(SuppressFormsAuthenticationRedirectModule));
}
public static void SuppressAuthenticationRedirect(HttpContext context)
{
context.Items[SuppressAuthenticationKey] = true;
}
public static void SuppressAuthenticationRedirect(HttpContextBase context)
{
context.Items[SuppressAuthenticationKey] = true;
}
public void Init(HttpApplication context)
{
context.PostReleaseRequestState += OnPostReleaseRequestState;
context.EndRequest += OnEndRequest;
}
public void Dispose()
{
}
private void OnPostReleaseRequestState(object source, EventArgs args)
{
var context = (HttpApplication)source;
var response = context.Response;
var request = context.Request;
if (response.StatusCode == 401 && request.Headers["X-Requested-With"] == "XMLHttpRequest")
{
SuppressAuthenticationRedirect(context.Context);
}
}
private void OnEndRequest(object source, EventArgs args)
{
var context = (HttpApplication)source;
var response = context.Response;
if (context.Context.Items.Contains(SuppressAuthenticationKey))
{
response.TrySkipIisCustomErrors = true;
response.ClearContent();
response.StatusCode = 401;
response.RedirectLocation = null;
}
}
}
和web.config
<modules>
<add name="SuppressFormsAuthenticationRedirectModule" type="SuppressFormsAuthenticationRedirectModule"/>
</modules>
答案 1 :(得分:3)
可以在http://kevin-junghans.blogspot.in/2013/12/returning-401-http-status-code-on.html
中找到问题的解决方案您需要像这样修改Startup
类:
public partial class Startup
{
private static bool IsAjaxRequest(IOwinRequest request)
{
IReadableStringCollection query = request.Query;
if ((query != null) && (query["X-Requested-With"] == "XMLHttpRequest"))
{
return true;
}
IHeaderDictionary headers = request.Headers;
return ((headers != null) && (headers["X-Requested-With"] == "XMLHttpRequest"));
}
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Enable the application to use a cookie to store information for the signed in user
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnApplyRedirect = ctx =>
{
if (!IsAjaxRequest(ctx.Request))
{
ctx.Response.Redirect(ctx.RedirectUri);
}
}
}
});
// Use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
}
}
答案 2 :(得分:1)
我使用返回404的simuler代码。您的代码可能是:
public ActionResult My()
{
if (User.Identity.IsAuthenticated == false)
{
return new HttpUnauthorizedResult();
}
// ... other code ...
}
答案 3 :(得分:0)
对于Identity中间件,可以通过在Startup.Auth.cs中删除LoginPath选项来禁用重定向:
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
...
LoginPath = new PathString("/Account/Login"), // Remove this line
});
答案 4 :(得分:0)
在Statup.cs中,我必须将AutomaticChallenge
设置为false
。一旦我这样做,它就停止了URL重定向(导致200状态),并给了我所需的401状态。
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
{
options.Cookies.ApplicationCookie.AutomaticChallenge = false; //<@@@@@@@
//...
})
.AddEntityFrameworkStores<ApplicationDbContext, int>()
.AddDefaultTokenProviders();
}
如果你设置了一些cookie中间件:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IAntiforgery antiforgery)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = "__auth__",
LoginPath = "/account/login",
AccessDeniedPath = "/account/forbidden",
AutomaticAuthenticate = true,
AutomaticChallenge = false //<@@@@@@@
});
}