开发工具与关键技术:Visual Studio 2015 LINQ
作者:孙水兵
撰写时间:2019年5月24
一、 功能
用户通过修改密码可以自行将自己的登录密码修改成自己想要的密码。
二、 达到的效果
用户先输入现在的密码,点击下一步。系统判断密码是否一致,如果不一致,如图中,在input框下面提示密码错误,如果一致,账号和旧密码框隐藏,显示出图二。并且图二需自动判断两次输入的密码是否一致,如果不一致,则不能提交数据。如果一致,则提交数据。
三、 代码
HTML代码
HTML代码主要分为三个部分,第一部分为用户验证部分,存在账号和旧密码,第二部分为修改密码部分,存在新密码、确认密码和验证码(关于验证码我这就不说了,之前说过。)第三部分则是两个按钮了,下一步按钮和提交按钮。第一部分和下一步按钮先让其显示,所以第二部分和提交按钮就先设置 display:none;。或许提交按钮可以不用写,可以用JS去更改下一步按钮中的文字,有兴趣的可以自己试一下。关于HTML代码的布局,主要的是用到了BootStrop4插件。在from表单中写这三部分。其中在密码框下加一个行内元素并设置id为tip1,用来提示。
<form class="form-horizontal row" role="form" id="formUpdatePassword" action="/Main/InsertUser" method="post">
<div class="col-12 col-lg-3 text-center mt-2"></div>
<div class="col-12 col-lg-9 row p-0 m-0">
<div class="col-12 col-lg-6 p-2 mb-0">
<div id="one">
<div class="form-group form-row">
<label class="col-form-label col-lg-2">账号:</label>
<div class="col-lg-9">
<input type="text" class="form-control w-75" id="IsUserNumber" name="UserNumber" value="@ViewBag.userNum" />
</div>
</div>
<div class="form-group form-row">
<label class="col-form-label col-lg-2">旧密码:</label>
<div class="col-lg-9">
<input type="password" name="Password" style="display:none;" />
<input type="password" class="form-control w-75" id="oldPassword" name="Password" autocomplete="new-password" placeholder="请输入密码" />
@*<input type="text" class="form-control w-75" id="oldPassword" name="Password" placeholder="请输入密码" onfocus="this.type='password'"/>*@
<div style="display: inline" id="tip1"></div>
</div>
</div>
</div>
<div style="display:none;" id="Two">
<div class="form-group form-row">
<label class="col-form-label col-lg-2">新密码:</label>
<div class="col-lg-9">
<input type="password" class="form-control w-75" id="newPassword" name="Password" />
<div style="display: inline" id="tip2"></div>
</div>
</div>
<div class="form-group form-row">
<label class="col-form-label col-lg-2">确认密码:</label>
<div class="col-lg-9">
<input type="password" class="form-control w-75" id="IsnewPassword" name="Password" />
<div style="display: inline" id="tip3"></div>
</div>
</div>
<div class="form-group form-row pl-2">
<label class="col-form-label col-lg-2" for="validCode">验证码:</label>
<input type="text" name="validCode" id="validCode" value="" class="form-control col-5 w-50" placeholder="验证码" />
<div style="display: inline" id="tip4"></div>
</div>
<div class="form-group form-row pl-2">
<span class="col-lg-2"></span>
<div><img src="/Main/ValideCode" width="100" height="38" id="validCodeImg" /></div>
</div>
</div>
<div class="form-group form-row pl-2">
<span class="col-lg-4"></span>
<button type="button" class="btn btn-light btn-block mt-3 " style="width:100px;" id="NextStepbtn">下一步</button>
<button type="button" class="btn btn-light btn-block mt-3 " style="width:100px; display:none;" id="btnSubmit" onclick="saveUpdateModel()">提交</button>
</div>
</div>
</div>
</form>
JS代码—第一部分:判断密码
在这个项目中,设置的是只有登入的用户本人才能更改本人的密码(管理员除外)。因此我在此设置的是将账号的input框设置为只读状态。账号由session中获取并传入页面的相应的位置。然后给下一步的按钮设置一个点击事件,在点击事件中获取到用户的账号和密码。第一步当然是判断密码是否为空,若密码为空,则提示输入密码,反之,将密码和账号传入控制器中并判断,若密码不正确,即控制器返回的数字是2,给tip1设置字体颜色为红色的密码错误的提示。反之,如果密码正确,给tip1设置字体颜色为绿色的密码正确的样式,并设置第一部分和下一步按钮隐藏,下一步和提交按钮显示。(strVallNotNull是一个判断是否为空的方法)
var layer;
$(function () {
layui.use(['layer'], function () {
layer = layui.layer;
})
//设置账户为只读状态,只允许修改自己的密码
var UserNumber = $("#UserNumber").val();
var input = $("#formUpdatePassword").find("input");
input[0].readOnly = true;//设置为只读状态
})
$("#NextStepbtn").click(function () {
var oldpassword = $("#oldPassword").val();
var IsUserNumber = $("#IsUserNumber").val();
if (strValIsNotNull(oldpassword)) {
$.post("/SetSystem/AmendPassword/verifyPassword", { oldpassword: oldpassword,
IsUserNumber: IsUserNumber }, function (strMsg) {
if (strMsg == "2") {
$("#tip1").html("<font color=\"red\" size=\"2\"> 密码错误</font>");
return; } else {
$("#tip1").html("<font color=\"green\" size=\"2\"> 密码正确</font>");
$("#one").css("display", "none"); $("#Two").css("display", "block");
$("#NextStepbtn").css("display", "none"); $("#btnSubmit").css("display", "block");
} })
} else {
layer.alert("请输入密码!");
}
});
控制器代码—传递数据到页面以及判断密码是否正确
上面一个方法是将用户的账号传递到页面,方便页面的账号input框设置为只读状态。先用try{}catch{}捕获异常。若出现异常,则跳转到登录页面,反之,从session中获取登录用户的用户ID(前提情况是已经将登入用户的用户ID保存到session中,在说登录时候提到过)。然后在利用linq从数据库中获取到用户的账号。然后利用ViewBag.自己命名=要传递的数据的名称,将数据传递到页面。然后在页面对应的位置 @ViewBag.自己命名 就能将数据传递到相应的地方。至于判断密码是否正确也很简单,先获取到页面传递过来的数据,然后利用linq从数据库中查询出对应账号下的密码(单条数据),然后对比密码。由于数据库中的密码用到了AES256加密,因此判断密码之前需要先将获取到的密码加密。若密码一致,返回1,不一致,返回2。
/// <summary>
/// 判断密码页面
/// </summary>
/// <returns></returns>
public ActionResult AmendPassword()
{
try
{
var UserID = Convert.ToInt32(Session["UserID"].ToString());
var userNum = (from tbUser in myModels.PW_User
where tbUser.UserID == UserID
select tbUser.UserNumber.Trim()).Single();
//存入session,方便后面调用
Session["UserNumber"] = userNum;
ViewBag.userNum = userNum;
}
catch (Exception e)
{
return Redirect("/Main/Login");
}
return View();
}
/// <summary>
/// 判断密码是否正确
/// </summary>
/// <param name="oldpassword"></param>
/// <returns></returns>
public ActionResult verifyPassword(string oldpassword,string IsUserNumber)
{
var strMsg = "";
try
{
var UserID = Convert.ToInt32(Session["UserID"].ToString());
var verifyPassword = (from tbUser in myModels.PW_User
where tbUser.UserNumber.Trim() == IsUserNumber.Trim()
select tbUser.Password).Single();
string password = AESEncryptHelper.Encrypt(oldpassword);
if (verifyPassword.Trim()== password)
{
strMsg = "1";
}
else
{
strMsg = "2";
}
}
catch (Exception e)
{
Console.Write(e);
}
return Json(strMsg, JsonRequestBehavior.AllowGet);
}
JS代码—第二部分:判断密码是否一致以及保存密码
给确认密码一个失去焦点事件,当确认密码框失去焦点时,判断新密码与确认密码是否一致。若不一致,输出提示密码不一致,并设置点击提交按钮弹出提示框。反之,输出提示密码一致。然后给提交按钮写点击事件,判断两个密码和验证码是否为空,然后提交验证码和新密码。若控制器中判断密码保存成功,弹出提示以及跳转到登录页面。否则弹出提示。每提交一次,将两个密码框和验证码框清空一次,以及刷新一次验证码。
$("#IsnewPassword").blur(function () {
var IsnewPassword = $("#IsnewPassword").val(); var newPassword = $("#newPassword").val();
if (newPassword != IsnewPassword) {
$("#tip3").html("<font color=\"red\" size=\"2\"> 新密码与确认密码不一致!</font>");
$("#btnSubmit").click(function () {
layer.alert("密码不一致!", { icon: 0, title: "提示" }); })
return;} else {
$("#tip3").html("<font color=\"green\" size=\"2\"> 新密码与确认密码一致!</font>");
function saveUpdateModel() { //保存修改的密码
var oldpassword = $("#oldPassword").val();
var IsnewPassword = $("#IsnewPassword").val();
var newPassword = $("#newPassword").val();
var validCode = $("#formUpdatePassword [name='validCode']").val();
if (strValIsNotNull(oldpassword) && strValIsNotNull(IsnewPassword) && strValIsNotNull(newPassword)) {
if (strValIsNotNull(validCode)) {
var layerIndex = layer.load();
$.post("/SetSystem/AmendPassword/UpdatePassword", { validCode: validCode, IsnewPassword: IsnewPassword }, function (data) {
layer.close(layerIndex);
if (data.State) {
layer.alert(data.Text, { icon: 1, title: "提示" }, function (index) {
layer.close(index);
window.location.href = "/Main/Login";
});
} else {
layer.alert(data.Text, { icon: 0, title: "提示" });
}
$("#IsnewPassword").val("");
$("#newPassword").val("");
$("#validCode").val("");
$("#validCodeImg").click();
});
} else {
layer.alert("请输入验证码!", { icon: 0, title: "提示" });
}
} else {
layer.alert("请填写完整!", { icon: 0, title: "提示" });
}
}
}
});
控制器代码—保存修改后的密码
保存修改密码的方法很简单,首先,先获取页面传递过来的验证码以及新密码。然后从session中获取图片的验证码,判断验证码是否正确(忽略大小写)。然后从数据库中查询出原来的密码并判断新密码是否和旧密码一致。如果一致,返回新密码和旧密码一致,反之保存修改。
/// <summary>
/// 保存修改后的密码
/// </summary>
/// <returns></returns>
public ActionResult UpdatePassword(string validCode,string IsnewPassword)
{
ReturnJsonVo returnJson = new ReturnJsonVo();
//判断验证码
//获取验证码
var sessionValidCode = "";
try
{
sessionValidCode = Session["ValideCode"].ToString();
}
catch (Exception e)
{
Console.Write(e);
}
if (sessionValidCode.Equals(validCode.Trim(), StringComparison.CurrentCultureIgnoreCase))
{
try
{
var strUserNumber = Session["UserNumber"].ToString();
PW_User dbUser = (from tbUser in myModels.PW_User
where tbUser.UserNumber.Trim() == strUserNumber.Trim()
select tbUser).Single();
//密码验证
//数据库中保存的密码是加密之后的密码,因此比较之前需要将输入的密码先进行加密
string password = AESEncryptHelper.Encrypt(IsnewPassword);
if (password.Trim() != dbUser.Password.Trim())
{
dbUser.Password=AESEncryptHelper.Encrypt(IsnewPassword);
myModels.Entry(dbUser).State = EntityState.Modified;
if (myModels.SaveChanges()>0)
{
returnJson.State = true;
returnJson.Text = "修改成功!";
}
else
{
returnJson.Text = "修改失败!";
}
}
else
{
returnJson.Text = "密码重复";
}
}
catch (Exception e)
{
Console.Write(e);
}
}
else
{
returnJson.Text = "验证码错误!";
}
return Json(returnJson, JsonRequestBehavior.AllowGet);
}
谷歌浏览器防止from表单填充密码的方法
谷歌中from表单密码的自动填充
之前
之后
方法一:先设置一个隐藏input框,再设置第二个展示的input框,最主要的是autocomplete=“new-password”
<input type="password" name="Password" style="display:none;" />
<input type="password" class="form-control w-75" id="oldPassword" name="Password" autocomplete="new-password" placeholder="请输入密码" />
方法二:浏览器保存密码是根据input="password"来判断的,所有我们只要保证浏览器在dom结构中识别不到密码框即可。设置input框的类型为文本框而不是密码框,然后在通过οnfοcus=“this.type=‘password’” 输入框获得焦点时改变输入框格式为密码框
<input type="text" class="form-control w-75" id="oldPassword" name="Password" placeholder="请输入密码" onfocus="this.type='password'"/>
详细解释:https://www.zhihu.com/question/23529765/answer/90632851