我有一个名为PasswordChangeChecker.cs
的类,它有一个从数据库返回的方法,无论用户是否更改了密码。该方法的签名是:
public bool IsPasswordChangedFromInitial(string IdOfUser)
其中IdOfUser
是Identity框架用户的Id字段。如果返回true,则表示不应显示更改密码页面,否则应导航到更改密码表单。用户成功更改密码后,将正确设置数据库标志,并且不会再次提示他们更改密码(除非管理员手动强制更改)。如何将此方法放在RouteConfig.cs
文件中,目前我所拥有的文件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace IdentityDevelopment
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
如何在defaults
参数中添加条件构造,以便我可以使用IsPasswordChangedFromInitial
方法来决定是否转到密码更改页面?该页面位于/Account/ChangePassword
。
修改
根据评论,我特定需要的相应操作方法是(我省略了不相关的代码):
登录后期操作:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginModel details, string returnUrl)
{
if (ModelState.IsValid)
{
AppUser user = await UserManager.FindAsync(details.Name,
details.Password);
if (user == null)
{
AppUser userByName = await UserManager.FindByNameAsync(details.Name);
if(userByName == null)
{
ModelState.AddModelError("", "Invalid username.");
}
else
{
//If this else is reached, it means the password entered is invalid.
//code for incrementing count of failed attempts and navigation to lock out page if needed
}
}
else
{
if(user.LockedOut)
{
//navigate to locked out page
}
else
{
PasswordChangeChecker PassCheck = new PasswordChangeChecker();
string userId = user.Id.ToString();
bool proceed = PassCheck.IsPasswordChangedFromInitial(userId);
//Authorize the user
ClaimsIdentity ident = await UserManager.CreateIdentityAsync(user,
DefaultAuthenticationTypes.ApplicationCookie);
ident.AddClaims(LocationClaimsProvider.GetClaims(ident));
ident.AddClaims(ClaimsRoles.CreateRolesFromClaims(ident));
AuthManager.SignOut();
AuthManager.SignIn(new AuthenticationProperties
{
IsPersistent = false
}, ident);
//persist login into db code
if (proceed)
{
//reset failed logins count
return Redirect(returnUrl);
}
else
{
return ChangePassword();
}
}
}
}
ViewBag.returnUrl = returnUrl;
return View(details);
}
ChangePassword()获取操作:
[HttpGet]
[Authorize]
public ActionResult ChangePassword()
{
return View();
}
以某种方式返回的视图是RouteConfig.cs
而不是ChangePassword.cshtml
页面中的视图。
谢谢。
答案 0 :(得分:1)
我会用全局动作过滤器
来做您可以使用方法
制作action filterprotected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (showChagePwPage)
{
//redirect to the change password page
filterContext.Result = new RedirectToActionResult("ChangePassword", "Account");
}
base.OnActionExecuting(filterContext);
}
然后通过
将其添加到全局操作过滤器中GlobalFilters.Filters.Add(yourFilterContext);
答案 1 :(得分:1)
经过几天与你相似的地狱般的运动,我试图在登录时路由用户,我意识到在登录帐户控制器时我无法获得UserId的价值。我做了一些实验,并提出了解决我问题的方法。
我在我的Home控制器中创建了一个ActionResult并将其命名为Purgatory(当然,一旦它被证明有效,我将其重命名为更合适的东西)。在那里,我填写了所有登录逻辑,用于在登录时将登录用户路由到各自的页面。
然后,在Account控制器的RedirectToLocal中,我更改了
return RedirectToAction("Index", "Home");
到
return RedirectToAction("Purgatory", "Home");
所以现在当用户登录时,如果returnTo参数未设置为特定页面,则returnTo参数将为null,当它到达RedirectToLocal时,它将降至以前重定向到的位置主页,现在将进入炼狱。
答案 2 :(得分:1)
这听起来是使用动作过滤器的好时机,您可以全局或按控制器/操作应用。
这是一个简单的例子:
using System;
using System.Web.Mvc;
using System.Web.Routing;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class VerifyPasswordChangedAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if(!filterContext.ActionDescriptor.ActionName.Equals("changepassword", StringComparison.OrdinalIgnoreCase))
{
if (filterContext.HttpContext.Request.IsAuthenticated)
{
var userName = filterContext.HttpContext.User.Identity.Name;
PasswordChangeChecker PassCheck = new PasswordChangeChecker();
if (!PassCheck.IsPasswordChangedFromInitial(userName))
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "account", action = "changepassword", area = string.Empty }));
}
}
}
base.OnActionExecuting(filterContext);
}
}
我会修改您的IsPasswordChangedFromInitial
方法,只是使用经过身份验证的用户的用户名,而不是试图弄清楚如何在动作过滤器中访问UserManager
实例。否则,假设您正在使用基于OWIN的ASP.NET标识,请在创建user.Id
时添加声明以存储ClaimsIdentity
字段,这样您就不必继续查找
最外面的条件处理这是一个全局过滤器的情况 - 没有它,你将获得无限重定向。