最近閑來無事給自己寫了家庭財務收支管理系統,也就包含支出管理,收入管理和一些統計功能。
先說登錄模塊,因為涉及GET和POST請求,這些東西都是能被監控和抓取的所以就考慮這使用RSA加密解密方式傳輸用戶名和密碼參數,頁面JS如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
/*需要引入三個JS文件,BigInt.js、RSA.js和Barrett.js,用到cookie則需要引入jquery.cookie.js文件*/ //與后臺交互獲取公鑰 function getPublicKey() { var pubKey = '' ; if ($.cookie( 'publicKey' ) == null ) { $.ajax({ url: "/Account/GetRsaPublicKey" , type: "get" , contentType: "application/x-www-form-urlencoded; charset=utf-8" , async: false , data: {}, dataType: "json" , success: function (data) { if (data.Code == 0) { pubKey = data.RsaPublicKey + "," + data.Key; $.cookie( 'publicKey' , pubKey, { expires: 1 / 1440 }); } else { Config.Method.JudgeCode(data, 1); } } }); } else { pubKey = $.cookie( 'publicKey' ); } return pubKey; } //公鑰加密用戶密碼Pwd為RSA加密后參數 function rsaEncrypt(pwd) { var publicKey = getPublicKey(); setMaxDigits(129); var rsaKey = new RSAKeyPair(publicKey.split( "," )[0], "" , publicKey.split( "," )[1]); var pwdRtn = encryptedString(rsaKey, pwd); return pwdRtn + "," + publicKey.split( "," )[2]; } //POST登錄請求,參數 <script type= "text/javascript" > $( function () { $( '#btnSubmit' ).live( 'click' , function () { var uName = $( '#u' ).val(); var pwd = $( '#p' ).val(); if (uName == '' ) { alert( '用戶名不能為空' ); return ; } if (pwd == '' ) { alert( '用戶密碼不能為空' ); return ; } var enPwd = rsaEncrypt(pwd); $.ajax({ type: "POST" , url: "/Account/UserLogin" , data: { 'UserName' : uName, 'Pwd' : enPwd.split( "," )[0], 'Key' : enPwd.split( "," )[1], 'RUrl' : $( '#hiddenUrl' ).val() }, contentType: "application/x-www-form-urlencoded; charset=utf-8" , async: false , dataType: "json" , success: function (data) { if (data.result == true ) { window.location.href = data.url; return false ; } else { $( '#msg' ).text(data.message); } }, error: function (XMLHttpRequest, textStatus, errorThrown) { $( '#msg' ).text(XMLHttpRequest.status + '||' + XMLHttpRequest.readyState + '||' + textStatus); } }); }); }) </script> |
前臺加密完成后就需要后臺做解密處理,解密完成后需要使用MD5加密現有密碼與數據庫中用戶密碼進行比較驗證,如果驗證通過則需要寫入cookie以便下次用戶能自 動登錄,由于cookie中我不希望用戶名和密碼都明碼存儲,我這里用到了AES加密的方式,自定義一個32位的加密密鑰對cookie進行加密解密處理,后臺c#代碼如 下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
[HttpPost] public JsonResult UserLogin( string UserName, string Pwd, string Key, string RUrl) { string privateKey = Common.CacheGet(Key) as string ; if (! string .IsNullOrEmpty(privateKey)) { if ( string .IsNullOrEmpty(UserName)) { return Json( new { result = false , message = "用戶名為空" }, JsonRequestBehavior.AllowGet); } if ( string .IsNullOrEmpty(Pwd)) { return Json( new { result = false , message = "用戶密碼為空" }, JsonRequestBehavior.AllowGet); } string pwd = Common.DecryptRSA(Pwd, privateKey); //私鑰解密 string md5Pwd = Common.NoneEncrypt(Common.NoneEncrypt(Common.NoneEncrypt(pwd, 1), 1), 1); //將解密后的值md5加密3次 AccountUnserInfo userInfo = bll.GetUserInfo(UserName.Trim(), md5Pwd); if (userInfo != null && userInfo.U_Id > 0) //用戶信息存在 { //用戶名、密碼放入cookie HttpCookie cookie = new HttpCookie( "fw_izz" ); //AES加密Cookie cookie[ "u_name" ] = AesEncryptHelper.EncryptAes(UserName); cookie[ "u_pwd" ] = AesEncryptHelper.EncryptAes(pwd); cookie.Expires = DateTime.Now.AddDays(7); Response.Cookies.Add(cookie); if (! string .IsNullOrEmpty(RUrl)) //接收隱藏域中的值 { return Json( new { result = true , message = "成功" , url = RUrl }); } else { return Json( new { result = true , message = "成功" , url = "/AccountDetail/Index" }); } } else { return Json( new { result = false , message = "用戶信息不存在" , url = "/Account/Index" }); } } else { return Json( new { result = false , message = "非法秘鑰" , url = "/Account/Index" }); } } |
各種加密解密方法、Cache操作以及cookie操作代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
public class Common { /// <summary> /// 產生一組RSA公鑰、私鑰 /// </summary> /// <returns></returns> public static Dictionary< string , string > CreateRsaKeyPair() { var keyPair = new Dictionary< string , string >(); var rsaProvider = new RSACryptoServiceProvider(1024); RSAParameters parameter = rsaProvider.ExportParameters( true ); keyPair.Add( "PUBLIC" , BytesToHexString(parameter.Exponent) + "," + BytesToHexString(parameter.Modulus)); keyPair.Add( "PRIVATE" , rsaProvider.ToXmlString( true )); return keyPair; } /// <summary> /// RSA解密字符串 /// </summary> /// <param name="encryptData">密文</param> /// <param name="privateKey">私鑰</param> /// <returns>明文</returns> public static string DecryptRSA( string encryptData, string privateKey) { string decryptData = "" ; try { var provider = new RSACryptoServiceProvider(); provider.FromXmlString(privateKey); byte [] result = provider.Decrypt(HexStringToBytes(encryptData), false ); ASCIIEncoding enc = new ASCIIEncoding(); decryptData = enc.GetString(result); } catch (Exception e) { throw new Exception( "RSA解密出錯!" , e); } return decryptData; } private static string BytesToHexString( byte [] input) { StringBuilder hexString = new StringBuilder(64); for ( int i = 0; i < input.Length; i++) { hexString.Append(String.Format( "{0:X2}" , input[i])); } return hexString.ToString(); } public static byte [] HexStringToBytes( string hex) { if (hex.Length == 0) { return new byte [] { 0 }; } if (hex.Length % 2 == 1) { hex = "0" + hex; } byte [] result = new byte [hex.Length / 2]; for ( int i = 0; i < hex.Length / 2; i++) { result[i] = byte .Parse(hex.Substring(2 * i, 2), System.Globalization.NumberStyles.AllowHexSpecifier); } return result; } private static ObjectCache Cache { get { return MemoryCache.Default; } } /// <summary> /// 獲取緩存 /// </summary> /// <param name="key"></param> /// <returns></returns> public static object CacheGet( string key) { return Cache[key]; } /// <summary> /// 設置緩存 /// </summary> /// <param name="key"></param> /// <param name="data"></param> /// <param name="cacheTime"></param> public static void CacheSet( string key, object data, int cacheTime) { CacheItemPolicy policy = new CacheItemPolicy(); policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime); Cache.Add( new CacheItem(key, data), policy); } /// <summary> /// 判斷緩存是否存在 /// </summary> /// <param name="key"></param> /// <returns></returns> public static bool IsSet( string key) { return (Cache[key] != null ); } /// <summary> /// 緩存失效 /// </summary> /// <param name="key"></param> public static void CacheRemove( string key) { Cache.Remove(key); } /// <summary> /// 對字符串進行加密(不可逆) /// </summary> /// <param name="Password">要加密的字符串</param> /// <param name="Format">加密方式,0 is SHA1,1 is MD5</param> /// <returns></returns> public static string NoneEncrypt( string Password, int Format) { string strResult = "" ; switch (Format) { case 0: strResult = FormsAuthentication.HashPasswordForStoringInConfigFile(Password, "SHA1" ); break ; case 1: strResult = FormsAuthentication.HashPasswordForStoringInConfigFile(Password, "MD5" ); break ; default : strResult = Password; break ; } return strResult; } } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。