我正在向
AuthorizeAttribute
添加自定义代码,将用户路由到另一个控制器中的操作,该控制器在用户尚未验证其电话号码时显示模式弹出窗口。
由于某种原因,代码只是永远重定向,网站只是说:
重定向您太多次
并且没有达到我在
VerifyPhoneNumber
操作中设置的断点。
您能说明为什么会发生这种情况吗? 短暂性脑缺血发作。
这是我的自定义重写的
AuthorizeAttribute
类,远低于此。 这里的所有内容以前都在这里,我只是添加了:
if (CustomContext.AccountDomainType == AccountDomainType.ActiveDirectory &&
CustomContext.IsPhoneNumberConfirmed == false)
{
return false;
}
并且:
if (CustomContext.AccountDomainType == AccountDomainType.ActiveDirectory &&
CustomContext.IsPhoneNumberConfirmed == false)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
{
{ "action", "VerifyPhoneNumber" },
{ "controller", "Account" }
});
return;
}
CustomAuthorizeAttribute
班级:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public Module Module { get; set; }
public Permission Permission { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var CustomContext = (Context)httpContext.Items[Context.HttpContextItemName];
var token = httpContext.Request.Form["token"];
if (!base.AuthorizeCore(httpContext) && token == null)
{
return false;
}
else if (token != null)
{
var tokenRepository = new AuthenticationTokenRepository(CustomContext);
var authenticationToken = tokenRepository.Get(token);
if (authenticationToken == null)
{
CustomContext.Log("Permission denied because authentication token was not valid");
return false;
}
var authenticationManager = httpContext.GetOwinContext().Authentication;
var userManager = httpContext.GetOwinContext().Get<AspNetUserManager>();
AspNetUser user;
if (authenticationToken.Role == AuthenticationTokenRole.PdfGenerator)
{
user = userManager.FindByName<AspNetUser, Guid>(authenticationToken.CreatedBy);
if (user == null)
{
CustomContext.Log("Permission denied because token creation user was not found");
return false;
}
}
else
{
return false;
}
var userIdentity = ApplicationSignInManager.GenerateUserIdentity(userManager, user, DefaultAuthenticationTypes.ApplicationCookie);
authenticationManager.SignIn(new AuthenticationProperties { IsPersistent = false }, userIdentity);
if (!authenticationManager.User.Identity.IsAuthenticated)
{
authenticationManager.User = authenticationManager.AuthenticationResponseGrant.Principal;
}
}
if (token == null && !CustomContext.IsDeviceAuthorized())
{
CustomContext.UpdateDevice();
httpContext.GetOwinContext().Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.TwoFactorCookie, DefaultAuthenticationTypes.ApplicationCookie);
CustomContext.Log("Permission denied and forced sign out because device was already signed out based on cookie check");
return false;
}
if (Module != default(Module) && Permission != default(Permission) && !CustomContext.HasPermission(Module, Permission))
{
CustomContext.Log("Permission denied because user does not have permission to " + Module.DisplayName() + ", " + Permission.DisplayName());
return false;
}
if (Module != default(Module) && Permission == default(Permission) && !CustomContext.HasModule(Module))
{
CustomContext.Log("Permission denied because company does not have the following module features turned on " + Module.DisplayName());
return false;
}
if (CustomContext.IsPasswordExpired
&& httpContext.Request.RequestContext.RouteData.Values.ContainsKey("action")
&& "ChangePassword" != httpContext.Request.RequestContext.RouteData.Values["action"].ToString()
&& "ChangePasswordLink" != httpContext.Request.RequestContext.RouteData.Values["action"].ToString())
{
CustomContext.Log("Permission denied because password is expired. Password must be changed first");
return false;
}
if (Module == default(Module) && Permission != default(Permission))
{
throw new Exception("No module specified for permission check");
}
if (CustomContext.AccountDomainType == AccountDomainType.ActiveDirectory &&
CustomContext.IsPhoneNumberConfirmed == false)
{
return false;
}
return true;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
var actionParams = filterContext.ActionDescriptor.GetParameters();
var paramTypes = actionParams.Select(ap => ap.ParameterType).ToArray();
var actionMethod = filterContext.Controller.GetType()
.GetMethod(filterContext.ActionDescriptor.ActionName, paramTypes);
var CustomContext = (Context)filterContext.HttpContext.Items[Context.HttpContextItemName];
var errorTypeViewPrefix = CustomContext.IsPasswordExpired ? "PasswordExpired" : "PermissionDenied";
if (CustomContext.AccountDomainType == AccountDomainType.ActiveDirectory &&
CustomContext.IsPhoneNumberConfirmed == false)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
{
{ "action", "VerifyPhoneNumber" },
{ "controller", "Account" }
});
return;
}
if (actionMethod != null && (actionMethod.ReturnType == typeof(PartialViewResult) ||
actionMethod.ReturnType == typeof(Task<PartialViewResult>)))
{
// Partial views
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
{
{ "action", errorTypeViewPrefix + "Partial" },
{ "controller", "Error" }
});
return;
}
// Full page views
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
{
{ "action", errorTypeViewPrefix },
{ "controller", "Error" }
});
return;
}
base.HandleUnauthorizedRequest(filterContext);
}
}
}
我尝试执行的操作,向用户发送文本消息代码并打开弹出窗口(它存在于另一个控制器中):
[Display(Name = "Verify Phone Number", Description = "Verify Phone Number")]
public async Task<PartialViewResult> VerifyPhoneNumber()
{
var strictPhoneAttr = new StrictPhoneAttribute();
if (!strictPhoneAttr.IsValid(Context.PhoneNumber))
{
ModelState.AddModelError(string.Empty, "Please, change your phone number to a valid cell phone number under the menu in the top right-hand corner under your name. A valid cell phone number is required for two-factor authentication used by this system.");
}
else
{
/....code that send SMS code ......./
Context.Log("Opened Verify Phone Number modal");
return PartialView("_VerifyPhoneNumber", new VerifyPhoneNumberModel());
}
确保当用户重定向到
VerifyPhoneNumber
操作时,他们不会自动再次重定向到原始操作(由于正在评估相同的条件),我认为您可以添加一些日志记录来改进调试。
一旦成功验证电话号码,您可能需要更改逻辑以更新
CustomContext.IsPhoneNumberConfirmed
,因为如果模式不允许用户解决问题,他们将继续被重定向。
您可以修改
AuthorizeCore
方法来检查当前操作是否为 VerifyPhoneNumber
。如果是这样,您可以跳过重定向:
if (filterContext.ActionDescriptor.ActionName == "VerifyPhoneNumber" && filterContext.ActionDescriptor.ControllerDescriptor.ControllerName == "Account")
{
return true;
}
HandleUnauthorizedRequest
方法中,您没有创建导致相同重定向的多个条件。AuthorizeCore
方法的修改部分,可避免重定向循环:if (CustomContext.AccountDomainType == AccountDomainType.ActiveDirectory &&
CustomContext.IsPhoneNumberConfirmed == false)
{
// check if we are already in the VerifyPhoneNumber action to prevent a redirect loop
if (!(httpContext.Request.RequestContext.RouteData.Values["action"].ToString() == "VerifyPhoneNumber" &&
httpContext.Request.RequestContext.RouteData.Values["controller"].ToString() == "Account"))
{
return false; // triggers redirect logic in HandleUnauthorizedRequest
}
}