我在单页应用程序中使用Breeze保存到asp.net web api服务器。我的应用程序正在使用表单身份验证,我的Breeze控制器使用Authorize属性进行修饰;
[System.Web.Http.Authorize]
[BreezeController]
public class ReminderController : ApiController
{ ... }
我看到一个问题,一旦Breeze尝试保存,在请求完成之前,浏览器会立即弹出用户名/密码验证对话框。我不完全确定为什么会发生这种情况,因为aspx cookie没有设置为过期但我可以通过登录我的应用程序,删除cookie然后触发Breeze保存来复制它。如果我在对话框上单击取消,我的服务器将响应一个我的客户端代码处理的401。我想确保永远不会向用户显示身份验证对话框。这种情况目前发生在Chrome和IE中,但我确信它在较早版本的Chrome稳定版中没有这样做。
此处可以看到请求,在显示对话框时仍显示为待处理
谢谢
答案 0 :(得分:1)
这是我在我们的应用程序中用于解决此问题的自定义Authorize属性(警告,从VB.NET自动转换为C#,因此它可能不是100%正确!)。如果用户已经过身份验证,它将发送403状态而不是401,以阻止浏览器提示用户登录。在IE和Firefox中测试过。
/// <summary>
/// Custom <see cref="AuthorizeAttribute"/> for WebAPI that sends a 403 Forbidden status instead
/// of 401 Unauthorized, if the user is authenticated, so that the browser will not display a
/// logon prompt.
/// </summary>
/// <remarks></remarks>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class MyAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
{
var user = Thread.CurrentPrincipal;
if (user != null && user.Identity.IsAuthenticated) {
// If the user is authenticated then we don't want to prompt them to authenticate.
// Ajax requests get a forbidden status code to stop the browser login prompt,
// since Unauthorized (401) would cause the browser to display a login dialog.
actionContext.Response = actionContext.ControllerContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Forbidden");
} else {
// If the user isn't authenticated then do the normal thing
base.HandleUnauthorizedRequest(actionContext);
}
}
}
答案 1 :(得分:0)
似乎没有可靠的跨浏览器方式来阻止客户端的对话。检查Fiddler我可以看到当cookie过期时对ajax请求的实际响应(令人讨厌的Chrome开发工具没有显示这个并且只是位于'待定')包含WWW-Authenticate
标题。奇怪的是,本地运行的IIS Express 不包含这些标题,对话从未显示。只有当我在我的提供商上发布到完整的IIS时才会显而易见。该计划是覆盖Web Api Authorize属性(处理授权失败的方法)并删除WWW-Authenticate
标题。
我不知道为什么IIS 8.0 / Express会返回不同的标题。