【发布时间】:2016-08-22 17:50:30
【问题描述】:
在一个使用Identity框架进行身份验证的系统中,我分别有以下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 中的控制器操作:
[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 操作方法?
编辑 1:
我包括用于登录的控制器方法,其中一个场景会导致出现 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;
}
}
}
谢谢。
【问题讨论】:
-
那么,当按钮被点击时会发生什么?你调试了吗?
-
您的代码看起来不错。你有没有拦截提交按钮的js代码。
-
@BviLLe_Kid 是的,我已经通过在控制器的 post 方法中放置断点进行了调试。当我点击按钮时,我被重定向到索引页面,但这不是因为在这个 post 方法中调用了索引,而是来自其他地方。
-
@Shyju 不,任何地方的按钮都没有 javascript 干扰。
-
您是否有全局身份验证过滤器或一些不寻常的路由表可以解释这种行为?
标签: c# asp.net asp.net-mvc asp.net-identity