在一个使用Identity framework进行身份验证的系统中,我分别有如下Model,Controller action,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
中的 Controller 操作:
[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>
}
为什么单击表单上的“保存”按钮不会调用发布操作方法?
编辑 1:
我包括了用于登录的 Controller 方法,其中一个场景导致 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;
}
}
}
谢谢。
最佳答案
如果你的 Action 没有被击中,而是转移到其他地方,那会让我相信正在发生以下两种情况之一:
您的路由表配置不正确
您有一个全局过滤器(尤其是全局授权过滤器)通过拦截请求并禁止或覆盖它来干扰您的预期行为。
通过调试和试错,您应该能够确定两种情况下的罪魁祸首。
关于c# - ASP.NET MVC 为什么不从 View 中调用此发布操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39085744/