最近闲来无事给自己写了家庭财务收支管理系统,也就包含支出管理,收入管理和一些统计功能。
先说登录模块,因为涉及GET和POST请求,这些东西都是能被监控和抓取的所以就考虑这使用RSA加密解密方式传输用户名和密码参数,页面JS如下:
1 /*需要引入三个JS文件,BigInt.js、RSA.js和Barrett.js,用到cookie则需要引入jquery.cookie.js文件*/ 2 //与后台交互获取公钥 3 function getPublicKey() { 4 var pubKey = ''; 5 if ($.cookie('publicKey') == null) { 6 $.ajax({ 7 url: "/Account/GetRsaPublicKey", 8 type: "get", 9 contentType: "application/x-www-form-urlencoded; charset=utf-8",10 async: false,11 data: {},12 dataType: "json",13 success: function (data) {14 if (data.Code == 0) {15 pubKey = data.RsaPublicKey + "," + data.Key;16 $.cookie('publicKey', pubKey, { expires: 1 / 1440 });17 } else {18 Config.Method.JudgeCode(data, 1);19 }20 }21 });22 } else {23 pubKey = $.cookie('publicKey');24 }25 return pubKey;26 }27 //公钥加密用户密码Pwd为RSA加密后参数28 function rsaEncrypt(pwd) {29 var publicKey = getPublicKey();30 setMaxDigits(129);31 var rsaKey = new RSAKeyPair(publicKey.split(",")[0], "", publicKey.split(",")[1]);32 var pwdRtn = encryptedString(rsaKey, pwd);33 return pwdRtn + "," + publicKey.split(",")[2];34 }35 //POST登录请求,参数36 <script type="text/javascript">37 $(function () {38 $('#btnSubmit').live('click', function () {39 var uName = $('#u').val();40 var pwd = $('#p').val();41 if (uName == '') {42 alert('用户名不能为空');43 return;44 }45 if (pwd == '') {46 alert('用户密码不能为空');47 return;48 }49 var enPwd = rsaEncrypt(pwd);50 $.ajax({51 type: "POST",52 url: "/Account/UserLogin",53 data: { 'UserName': uName, 'Pwd': enPwd.split(",")[0], 'Key': enPwd.split(",")[1], 'RUrl': $('#hiddenUrl').val() },54 contentType: "application/x-www-form-urlencoded; charset=utf-8",55 async: false,56 dataType: "json",57 success: function (data) {58 if (data.result == true) {59 window.location.href = data.url;60 return false;61 } else {62 $('#msg').text(data.message);63 }64 },65 error: function (66 $('#msg').text( textStatus);67 }68 });69 });70 })71 </script>
View Code
前台加密完成后就需要后台做解密处理,解密完成后需要使用MD5加密现有密码与数据库中用户密码进行比较验证,如果验证通过则需要写入cookie以便下次用户能自 动登录,由于cookie中我不希望用户名和密码都明码存储,我这里用到了AES加密的方式,自定义一个32位的加密密钥对cookie进行加密解密处理,后台c#代码如 下:
1 [HttpPost] 2 public JsonResult UserLogin(string UserName, string Pwd, string Key, string RUrl) 3 { 4 string privateKey = Common.CacheGet(Key) as string; 5 if (!string.IsNullOrEmpty(privateKey)) 6 { 7 if (string.IsNullOrEmpty(UserName)) 8 { 9 return Json(new { result = false, message = "用户名为空" }, JsonRequestBehavior.AllowGet);10 }11 if (string.IsNullOrEmpty(Pwd))12 {13 return Json(new { result = false, message = "用户密码为空" }, JsonRequestBehavior.AllowGet);14 }15 string pwd = Common.DecryptRSA(Pwd, privateKey);//私钥解密16 string md5Pwd = Common.NoneEncrypt(Common.NoneEncrypt(Common.NoneEncrypt(pwd, 1), 1), 1);//将解密后的值md5加密3次17 AccountUnserInfo userInfo = bll.GetUserInfo(UserName.Trim(), md5Pwd);18 if (userInfo != null && userInfo.U_Id > 0)//用户信息存在19 {20 //用户名、密码放入cookie21 HttpCookie cookie = new HttpCookie("fw_izz");22 //AES加密Cookie23 cookie["u_name"] = AesEncryptHelper.EncryptAes(UserName);24 cookie["u_pwd"] = AesEncryptHelper.EncryptAes(pwd);25 cookie.Expires = DateTime.Now.AddDays(7);26 Response.Cookies.Add(cookie);27 if (!string.IsNullOrEmpty(RUrl))//接收隐藏域中的值28 {29 return Json(new { result = true, message = "成功", url = RUrl });30 }31 else32 {33 return Json(new { result = true, message = "成功", url = "/AccountDetail/Index" });34 }35 }36 else37 {38 return Json(new { result = false, message = "用户信息不存在", url = "/Account/Index" });39 }40 }41 else42 {43 return Json(new { result = false, message = "非法秘钥", url = "/Account/Index" });44 }45 }
View Code
各种加密解密方法、Cache操作以及cookie操作代码如下:
1 public class Common 2 { 3 /// <summary> 4 /// 产生一组RSA公钥、私钥 5 /// </summary> 6 /// <returns></returns> 7 public static Dictionary<string, string> CreateRsaKeyPair() 8 { 9 var keyPair = new Dictionary<string, string>(); 10 var rsaProvider = new RSACryptoServiceProvider(1024); 11 RSAParameters parameter = rsaProvider.ExportParameters(true); 12 keyPair.Add("PUBLIC", BytesToHexString(parameter.Exponent) + "," + BytesToHexString(parameter.Modulus)); 13 keyPair.Add("PRIVATE", rsaProvider.Totrue)); 14 return keyPair; 15 } 16 17 /// <summary> 18 /// RSA解密字符串 19 /// </summary> 20 /// <param name="encryptData">密文</param> 21 /// <param name="privateKey">私钥</param> 22 /// <returns>明文</returns> 23 public static string DecryptRSA(string encryptData, string privateKey) 24 { 25 string decryptData = ""; 26 try 27 { 28 var provider = new RSACryptoServiceProvider(); 29 provider.From 30 31 byte[] result = provider.Decrypt(HexStringToBytes(encryptData), false); 32 ASCIIEncoding enc = new ASCIIEncoding(); 33 decryptData = enc.GetString(result); 34 } 35 catch (Exception e) 36 { 37 throw new Exception("RSA解密出错!", e); 38 } 39 return decryptData; 40 } 41 42 private static string BytesToHexString(byte[] input) 43 { 44 StringBuilder hexString = new StringBuilder(64); 45 46 for (int i = 0; i < input.Length; i++) 47 { 48 hexString.Append(String.Format("{0:X2}", input[i])); 49 } 50 return hexString.ToString(); 51 } 52 53 public static byte[] HexStringToBytes(string hex) 54 { 55 if (hex.Length == 0) 56 { 57 return new byte[] { 0 }; 58 } 59 if (hex.Length % 2 == 1) 60 { 61 hex = "0" + hex; 62 } 63 byte[] result = new byte[hex.Length / 2]; 64 for (int i = 0; i < hex.Length / 2; i++) 65 { 66 result[i] = byte.Parse(hex.Substring(2 * i, 2), System.Globalization.NumberStyles.AllowHexSpecifier); 67 } 68 return result; 69 } 70 71 private static ObjectCache Cache 72 { 73 get { return MemoryCache.Default; } 74 } 75 /// <summary> 76 /// 获取缓存 77 /// </summary> 78 /// <param name="key"></param> 79 /// <returns></returns> 80 public static object CacheGet(string key) 81 { 82 return Cache[key]; 83 } 84 /// <summary> 85 /// 设置缓存 86 /// </summary> 87 /// <param name="key"></param> 88 /// <param name="data"></param> 89 /// <param name="cacheTime"></param> 90 public static void CacheSet(string key, object data, int cacheTime) 91 { 92 CacheItemPolicy policy = new CacheItemPolicy(); 93 policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime); 94 Cache.Add(new CacheItem(key, data), policy); 95 } 96 /// <summary> 97 /// 判断缓存是否存在 98 /// </summary> 99 /// <param name="key"></param>100 /// <returns></returns>101 public static bool IsSet(string key)102 {103 return (Cache[key] != null);104 }105 /// <summary>106 /// 缓存失效107 /// </summary>108 /// <param name="key"></param>109 public static void CacheRemove(string key)110 {111 Cache.Remove(key);112 }113 /// <summary>114 /// 对字符串进行加密(不可逆)115 /// </summary>116 /// <param name="Password">要加密的字符串</param>117 /// <param name="Format">加密方式,0 is SHA1,1 is MD5</param>118 /// <returns></returns>119 public static string NoneEncrypt(string Password, int Format)120 {121 string strResult = "";122 switch (Format)123 {124 case 0:125 strResult = FormsAuthentication.HashPasswordForStoringInConfigFile(Password, "SHA1");126 break;127 case 1:128 strResult = FormsAuthentication.HashPasswordForStoringInConfigFile(Password, "MD5");129 break;130 default:131 strResult = Password;132 break;133 }134 return strResult;135 }136 }
View Code
原标题:ASP.NET MVC结合JavaScript登录、校验和加密
关键词:ASP.NET