为了控制和记录访问,很多系统都有登录页面,输入账户、密码和验证码后提交到服务器。在客户端和服务器之间传输数据时,需要传输加密过的数据,以免数据泄露,本文试用RSA加密实现这一过程;
客户端代码:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>后台管理登录</title>
<link href="~/Areas/HotelWebMge/Styles/AdminCss.css" rel="stylesheet" type="text/css" />
<script src="~/Scripts/jquery-1.8.2.js"></script>
<script src="~/Scripts/crypto/BigInt.js"></script>
<script src="~/Scripts/crypto/RSA.js"></script>
<script src="~/Scripts/crypto/Barrett.js"></script>
<script src="~/Scripts/crypto/Base64.js"></script>
<script type="text/javascript">
$(function () {
//键盘登录
$(document).keydown(function (event) {
//Enter键登录
if (event.keyCode == 13) {
login();
}
});
//按钮登录
$('#btnlogin').click(
login
);
});
function login() {
var txtLoginId = $('#txtLoginId').val();
//加密密码后赋值更新
var txtLoginPwd = $('#txtLoginPwd').val();
if (txtLoginPwd.length <= 5) {
$('#ItaInfo').text("密码不能少于6位!");
return;
}
var base = new Base64();
var baseLoginPwd = base.encode(txtLoginPwd);
var EncryptedPwd = cmdEncrypt(baseLoginPwd);
//$('#txtLoginPwd').val(EncryptedPwd);
var sdata = { "LoginId": txtLoginId, "LoginPwd": EncryptedPwd };
//异步提交
$.ajax({
url: '@Url.Content("~/HotelWebMge/SysAdmins/SysLogin")',
type: 'post',
//data: $('#form1').serialize(),
data: sdata,
beforeSend: function () {
$('#ItaInfo').text("...正在提交...请稍候!");
//alert($('#form1').serialize());
},
dataType: 'JSON',
error: function (xhr, status, error) {
$('#ItaInfo').text("输入字符串的格式不正确,登录失败!");
},
success: function (data) {
//登录成功
if (data == "1") {
window.location.href = '@Url.Action("Index", "Company", new{area="HotelWebMge"})';
} else {
$('#ItaInfo').text("用户名或密码错误!");
};
},
complete: function () {
//$('#ItaInfo').empty();
}
});
}
//加密函数,2019-01-16
function cmdEncrypt2(value) {
setMaxDigits(130);
var key = new RSAKeyPair("@ViewBag.strPublicKeyExponent", "", "@ViewBag.strPublicKeyModulus");
//var pwdMD5Twice = $.md5($.md5(value));
//var pwdRtn = encryptedString(key, pwdMD5Twice);
var valueRtn = encryptedString(key, value);
return valueRtn;
}
//分段加密,2019-06-11
function cmdEncrypt(value) {
setMaxDigits(130);
var key = new RSAKeyPair("@ViewBag.strPublicKeyExponent", "", "@ViewBag.strPublicKeyModulus");
//获取组块大小
var maxLength = key.chunkSize;
//生成长度正则
var seg = new RegExp('.{1,' + maxLength.toString() + '}', 'g');
try {
var lt = "";
var ct = "";
if (value.length > maxLength) {
lt = value.match(seg);
lt.forEach(function (entry) {
var t1 = encryptedString(key, entry);
ct += t1;
});
return (ct);
}
var t = encryptedString(key, value);
return t;
} catch (ex) {
return false;
}
//var valueRtn = encryptedString(key, value);
//return valueRtn;
}
//分段加密
//参考https://blog.csdn.net/qq_28027903/article/details/73289156
function segEncode(str) {
//var k = this.getKey();
//var maxLength = (((k.n.bitLength()+7)>>3)-11);
var maxLength = 117;
var seg = new RegExp('.{1,' + maxLength.toString() + '}', 'g');
try {
var lt = "";
var ct = "";
if (str.length > maxLength) {
lt = str.match(seg);
lt.forEach(function (entry) {
var t1 = k.encrypt(entry);
ct += t1;
});
return hex2b64(ct);
}
var t = k.encrypt(str);
var y = hex2b64(t);
return y;
} catch (ex) {
return false;
}
};
</script>
</head>
<body>
<form id="form1">
<div id="container">
<div id="top">
</div>
<div id="content">
<div id="loginimg">
<img src="~/Areas/HotelWebMge/Styles/Images/loginimg.jpg" alt="" />
</div>
<div id="logindiv">
<div id="ltitle">
管理员登录
</div>
<div class="litem">
登录账号:<input name="LoginId" type="text" id="txtLoginId" class="txt" />
</div>
<div class="litem">
登录密码:<input name="LoginPwd" type="password" id="txtLoginPwd" class="txt"
onpaste="return false" oncontextmenu="return false" oncopy="return false" oncut="return false" />
</div>
<div class="litem">
<input type="button" name="btnlogin" value="马上登录" id="btnlogin" class="btncss" />
</div>
<div class="loginInfo" id="ItaInfo"></div>
</div>
</div>
<div id="footer">
<div id="bq">
版权所有 Copyright(C)2010-2020
</div>
</div>
</div>
</form>
</body>
</html>
服务器代码:
public class SysAdminsController : Controller
{
/*参考网站如下,2019-01-16
* https://www.cnblogs.com/guogangj/archive/2012/03/05/2381117.html
* https://blog.csdn.net/angle_greensky110/article/details/48293653
* https://www.cnblogs.com/wenghaowen/p/3912132.html
* https://www.cnblogs.com/alunchen/p/5758585.html
*
* https://blog.csdn.net/xiaouncle/article/details/54913102
*/
//
// GET: /HotelWebMge/SysAdmins/
/// <summary>
/// 后台管理登录入口
/// </summary>
/// <returns></returns>
public ActionResult AdminLogin()
{
RSACryptoServiceProvider rsaKeyGenerator = new RSACryptoServiceProvider(1024);
//产生一对公钥私钥
//把公钥适当转换,准备发往客户端
RSAParameters parameter = rsaKeyGenerator.ExportParameters(true);
string strPublicKeyExponent = StringHelper.BytesToHexString(parameter.Exponent);
string strPublicKeyModulus = StringHelper.BytesToHexString(parameter.Modulus);
//传递公钥到页面
ViewBag.strPublicKeyExponent = strPublicKeyExponent;
ViewBag.strPublicKeyModulus = strPublicKeyModulus;
//BitConverter.ToString("fgf")
//将私钥存Session中
Session["privatekey"] = rsaKeyGenerator.ToXmlString(true);
return View("AdminLogin");
}
/// <summary>
/// 后台登录处理
/// </summary>
/// <returns></returns>
public ActionResult SysLogin(SysAdmins obj)
{
//取出私钥
string privatekey = Session["privatekey"].ToString();
//解密密码
RSACryptoServiceProvider rsaKeyGenerator = new RSACryptoServiceProvider(1024);
rsaKeyGenerator.FromXmlString(privatekey);
//加载密文,2019-06-11
byte[] dataEnc = StringHelper.HexStringToBytes(obj.LoginPwd);
int keySize = rsaKeyGenerator.KeySize / 8;
byte[] buffer = new byte[keySize];
MemoryStream msInput = new MemoryStream(dataEnc);
MemoryStream msOutput = new MemoryStream();
int readLen = msInput.Read(buffer, 0, keySize);
while (readLen > 0)
{
byte[] dataToDec = new byte[readLen];
Array.Copy(buffer, 0, dataToDec, 0, readLen);
byte[] decData = rsaKeyGenerator.Decrypt(dataToDec, false);
msOutput.Write(decData, 0, decData.Length);
readLen = msInput.Read(buffer, 0, keySize);
}
msInput.Close();
byte[] result = msOutput.ToArray();
System.Text.ASCIIEncoding ByteConverter = new ASCIIEncoding();
string sLoginPwd = ByteConverter.GetString(result);
byte[] bytes = Convert.FromBase64String(sLoginPwd);
obj.LoginPwd = Encoding.UTF8.GetString(bytes);
//生产环境要加密后再和数据库比对,此处数据库使用明码,省略这一步
//查询登录对象
obj = new SysAdminsMge().SysLogin(obj);
//返回视图
if (obj == null)
{
//ViewData["LoginUser"] = "用户名或密码错误!";
//return View();
return Content("0");
}
else
{//清除私钥
Session.Remove("privatekey");
Session["CurrentAdmin"] = obj;
FormsAuthentication.SetAuthCookie(obj.LoginName,true);
return Content("1");
}
}
}