在使用Identity framework进行身份验证的系统中,我分别使用以下Model,Controller操作和View来实现密码更改功能(我看到很多文章用于学习如何重置密码,但不知道如何更改密码密码,即使当前的密码已知):
型号:
public class ChangePasswordBindingModel
{
[Required]
[DataType(DataType.Password)]
public string OldPassword { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "New password")]
public string NewPassword { get; set; }
[Required]
[DataType(DataType.Password)]
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
AccountController.cs
中的控制器操作:
[HttpPost]
public async Task<ActionResult> ChangePassword(ChangePasswordBindingModel loginChange)
{
IdentityResult fffx = await UserManager.ChangePasswordAsync("userId", loginChange.OldPassword, loginChange.NewPassword);
return View("Index");
}
查看密码更改表单,名为ChangePassword.cshtml
:
@model IdentityDevelopment.Models.ChangePasswordBindingModel
@{ ViewBag.Title = "ChangePassword";}
<h2>Change Password</h2>
@using (Html.BeginForm("ChangePassword","Account", FormMethod.Post))
{
//@Html.AntiForgeryToken();
<input type="hidden" name="returnUrl" value="@ViewBag.returnUrl" />
<div class="form-group">
<label>Current Password</label>
@Html.PasswordFor(x => x.OldPassword, new { @class = "form-control" })
</div>
<div class="form-group">
<label>New Password</label>
@Html.PasswordFor(x => x.NewPassword, new { @class = "form-control" })
</div>
<div class="form-group">
<label>Re-enter New Password</label>
@Html.PasswordFor(x => x.ConfirmPassword, new { @class = "form-control" })
</div>
<button class="btn btn-primary" type="submit">Save</button>
}
为什么单击表单上的“保存”按钮不会调用post action方法?
编辑1:
我包含Login的控制器方法,其中场景导致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)
{
ModelState.AddModelError("", "Invalid name or password.");
}
else
{
//Check if this is initial login of user, force password change if so
PasswordChangeChecker PassCheck = new PasswordChangeChecker();
string userId = user.Id.ToString();
bool proceed = PassCheck.IsPasswordChangedFromInitial(userId);
if (proceed)
{
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
Loginobject login = new Loginobject();
login.Username = user.UserName;
login.SessionId = HttpContext.Session.SessionID;
Session["sessionid"] = HttpContext.Session.SessionID;
login.Date = DateTime.Now;
SQLLoginrecord sqlLogin = new SQLLoginrecord();
sqlLogin.PutOrPostLogin(login);
TempData["LoginMsg"] = "Any existing sessions are now deactivated.";
return Redirect(returnUrl);
}
else
{
return View("ChangePassword", new ChangePasswordBindingModel());
}
}
}
ViewBag.returnUrl = returnUrl;
return View(details);
}
编辑2:
看起来问题的原因是全局自定义授权过滤器(感谢评论stephen.vakil)[AuthorizeSingleLogin]
我已经提出AccountController.cs
的定义
AuthorizeSingleLogin.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace IdentityDevelopment.Infrastructure
{
public class AuthorizeSingleLogin : AuthorizeAttribute
{
private AppIdentityDbContext db = new AppIdentityDbContext();
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool isAuthorized = base.AuthorizeCore(httpContext);
string user = httpContext.User.Identity.Name;
string access = httpContext.Session.SessionID;
if (String.IsNullOrEmpty(user) || String.IsNullOrEmpty(access))
{
return isAuthorized;
}
SQLLoginrecord sqlLogin = new SQLLoginrecord();
return sqlLogin.IsLoggedIn(user, access);
}
}
}
SQLLoginrecord.cs
using IdentityDevelopment.Models;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using static IdentityDevelopment.Models.Loginobject;
namespace IdentityDevelopment.Infrastructure
{
public class SQLLoginrecord
{
private LoginobjectDBContext db = new LoginobjectDBContext();
private bool PriorSessionActive = false;
public void PutOrPostLogin(Loginobject login)
{
var logins = db.Loginobjects.Where(l => l.Username == login.Username);
if (logins.Any())
{
Loginobject tempLogin = logins.First();
tempLogin.SessionId = login.SessionId;
tempLogin.Date = login.Date;
db.Entry(tempLogin).State = EntityState.Modified;
PriorSessionActive = true;
}
else
{
db.Loginobjects.Add(login);
}
db.SaveChanges();
}
public bool IsLoggedIn(string user, string session)
{
var logins = db.Loginobjects.Where(l => l.Username == user && l.SessionId == session);
if (logins.Any())
{
return true;
}
else
{
return false;
}
}
public bool PriorSessionUpdated()
{
return this.PriorSessionActive;
}
}
}
谢谢。
答案 0 :(得分:3)
您
<button class="btn btn-primary" type="submit">Save</button>
元素必须是
<input class="btn btn-primary" type="submit" value="Save"/>
元素。
答案 1 :(得分:3)
如果你的行动没有在帖子上被击中,而是转到其他地方,那将导致我相信发生了两件事之一:
您的路由表配置不正确
您有一个全局过滤器(尤其是全局授权过滤器),它通过拦截请求并禁止或覆盖请求来干扰您的预期行为。
通过调试和试错,你应该能够在任何一种情况下确定罪魁祸首。