Vue、Vuex+Cookie 實現自動登陸 。


概述

  1、自動登陸實現思路。

  2、vuex + cookie 多標簽頁狀態保持。

自動登陸的需求:

  1、登陸時勾選自動登陸,退出登陸登陸到期后再次登陸后自動填寫表單(記住密碼)或訪問登陸頁自動登陸。

  2、安全性需求,cookie 的有效性判斷應該放到服務端。

實現細節

  1、后台:一個靜態的登陸管理類 負責管理登陸用戶,這里設計了兩個 cookie 一個用來保存登陸信息、一個用來保存自動登陸信息。

登陸cookie 的有效時間是 30 分鍾,自動登陸cookie 的有效時間是 3 天,分別保存了用戶名、編碼、密碼;用戶名、編碼、密碼、時間戳。

后台包含,RSA加密算法、cookie 管理、登陸相關業務(登入、登出、過濾器)。不干興趣跳過,看前端代碼。

  1     /// <summary>
  2     /// 登錄用戶管理
  3     /// </summary>
  4     public static class LoginUserManager
  5     {
  6         public const string DBENLOGININ = "DBEN.OP.LOGININ";
  7         public const string DBENAUTOLOGIN = "DBEN.OP.AUTOLOGIN";
  8         public const string DBENUSERCODE = "DBEN.OP.USERCODE";
  9         public const string DBENUSERNAME = "DBEN.OP.USERNAME";
 10         public const string DBENUSERPWD = "DBEN.OP.USERPASSWORD";
 11 
 12         /// <summary>
 13         /// RSA 加解密實例
 14         /// </summary>
 15         public static RSAApply RSAApply
 16         {
 17             get
 18             {
 19                 return new RSAApply(
 20          ConfigHelper.GetAppSetting("DBEN.StaticRSAPublicKey", @"MIGfM
 21 A0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBRxFQos7Nc77goLB6cz2SM6Ae7OuuOTkycG2eyP
 22 Lds7+hE8s6bqJMfdY6EOlPjGraATXSCsrPnowWeq2p59xyejJLlCfX3dE+Br5FuUG+MwK7K6i
 23 HQ2lJLZlvnnmDqjmHO2+k14VOFwlXNOKkciWVsjT/mr4Xj4olG2gjOhWvqQIDAQAB"),
 24          ConfigHelper.GetAppSetting("DBEN.StaticRSAPrivateKey", @"MIIC
 25 dwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMFHEVCizs1zvuCgsHpzPZIzoB7s6
 26 645OTJwbZ7I8t2zv6ETyzpuokx91joQ6U+MatoBNdIKys+ejBZ6rann3HJ6MkuUJ9fd0T4Gvk
 27 W5Qb4zArsrqIdDaUktmW+eeYOqOYc7b6TXhU4XCVc04qRyJZWyNP+avhePiiUbaCM6Fa+pAgM
 28 BAAECgYAePxDmnZPfcw2b+YmkoAQyrQGR1WHMkgfxbMa64pefOlHy0zYqnsWnUsoDrEHWwRK3
 29 qxjRFf9HHnity+UBgddtjRrSW9ly+5zSvTTVb3wHfSqV/xJsakZ3M8MjVLCQXZarXTbRlYBnx
 30 eFLcvvfouDHbefK6cqIpEk1uWllq7eNQQJBAOpWf2gsvGnFTU0vrx77Ed1QHH0C4ldss63N91
 31 /YbrmNl9jQNcWD2DG3tw3ToSM8JIAb1Rdw9/kwpoqW9qp0mI8CQQDTJOWQum/+oovU7MZrgzR
 32 K3N/wVXt4GIDgL4k48NSvzA+jRGf5MdphsqQKHuws9F4O+P7w/mK2QOHx4ys8OqBHAkEAnj6L
 33 Cu4qzcJO0TDCMUmaZrkSg9jOv/rH2zabNj4Rh3v2bpMrvJWsCObm1o9y4Thb7abd31aKHdycm
 34 joXmEPkQQJAW62hn/3TsxSQ8pr8bKJDil3tPkVfnv3Et5LsWjT3pH1OLO3+10y2LcWLRHm4wq
 35 w4SvgCelF6OvhhIs4ob7Zk8QJBAIXEwsLcy9xZaRt85dIWuJFfbuAmCXiNWSJEhIFYPkLUvi2
 36 QHZTdLHpSbi5oCPIVKw4CDTAP4b+JfGrrFaZjWNc="));
 37             }
 38         }
 39 
 40         /// <summary>
 41         /// 已登錄
 42         /// </summary>
 43         /// <param name="userCode"></param>
 44         public static void SetLoginIn(string userCode, string userName, string userPassword)
 45         {
 46             var dic = new Dictionary<string, string>
 47             {
 48                 { DBENUSERCODE, userCode },
 49                 { DBENUSERNAME, userName },
 50                 { DBENUSERPWD, userPassword }
 51             };
 52             CookieManager.SetCookie(DBENLOGININ, RSAApply.GetCiphertext(dic, false));
 53         }
 54 
 55         public static void SetLoginOut()
 56         {
 57             CookieManager.RemoveCookie(DBENLOGININ);
 58         }
 59 
 60         /// <summary>
 61         /// 自動登錄
 62         /// </summary>
 63         /// <param name="userCode"></param>
 64         public static void SetAutoLogin(string userCode, string userName, string userPassword)
 65         {
 66             if (CookieManager.GetCookie(DBENAUTOLOGIN) == null)
 67             {
 68                 //首次勾選自動登錄,創建自動登錄的cookie。
 69                 var dic = new Dictionary<string, string>
 70                 {
 71                     { DBENUSERCODE, userCode },
 72                     { DBENUSERNAME, userName },
 73                     { DBENUSERPWD, userPassword }
 74                 };
 75                 CookieManager.SetCookie(new HttpCookie(DBENAUTOLOGIN, RSAApply.GetCiphertext(dic, true)) { Expires = DateTime.Now.AddDays(RSAApply.ValidityDays) });
 76             }
 77             //通過自動登錄也要設置已登錄的 cookie
 78             SetLoginIn(userCode, userName, userPassword);
 79         }
 80 
 81         /// <summary>
 82         /// 檢查客戶端狀態
 83         /// </summary>
 84         /// <returns></returns>
 85         public static bool CheckClientStatus(out Dictionary<string, string> user)
 86         {
 87             /****
 88              * 如果存在 已登錄 cookie 且譯文有效,用戶未被禁用,則返回true
 89              * 否則檢驗 自動登錄 cookie。
 90              * 自動登錄 cookie 存在且譯文有效,自動登錄后返回 true。
 91              * */
 92 
 93             var cookie = CookieManager.GetCookie(DBENLOGININ);
 94             if (cookie != null)
 95             {
 96                 return CheckCiphertext(cookie.Value, out user);
 97             }
 98             else
 99             {
100                 // 如果不是已登錄,檢查是否存在自動登錄 cookie
101                 cookie = CookieManager.GetCookie(DBENAUTOLOGIN);
102                 if (cookie != null)
103                 {
104                     if (CheckCiphertext(cookie.Value, out user))
105                     {
106                         //將此用戶設置為已登錄
107                         SetLoginIn(user[DBENUSERCODE], user[DBENUSERNAME], user[DBENUSERPWD]);
108                         return true;
109                     }
110                 }
111                 user = null;
112                 return false;
113             }
114         }
115 
116         /// <summary>
117         /// 獲取客戶端用戶信息
118         /// </summary>
119         /// <returns>返回一個從 cookie 創建的新實例</returns>
120         public static OPUserEntity GetClientUserInfo()
121         {
122             OPUserEntity res = null;
123             if (CheckClientStatus(out Dictionary<string, string> user))
124             {
125                 res = new OPUserEntity
126                 {
127                     Code = user[DBENUSERCODE],
128                     UserName = user[DBENUSERNAME],
129                     Password = user[DBENUSERPWD]
130                 };
131             }
132             return res;
133         }
134 
135         /// <summary>
136         /// 校驗密文有效性,包括密文能否解密、賬戶有效性。
137         /// </summary>
138         /// <param name="ciphertext">密文</param>
139         /// <param name="user">如果返回值為方式則返回一個空實例</param>
140         /// <returns></returns>
141         private static bool CheckCiphertext(string ciphertext, out Dictionary<string, string> user)
142         {
143             user = new Dictionary<string, string>();
144             var repo = RF.ResolveInstance<OPUserEntityRepository>();
145             if (RSAApply.TryGetSource(ciphertext, ref user))
146             {
147                 if (user.TryGetValue(DBENUSERCODE, out string userCode))
148                 {
149                     if (user.TryGetValue(DBENUSERPWD, out string userPwd))
150                     {
151                         if (user.TryGetValue(DBENUSERNAME, out string userName))
152                         {
153                             var count = repo.CountBy(new CommonQueryCriteria
154                             {
155                                 { OPUserEntity.UserNameProperty,userName },
156                                 { OPUserEntity.CodeProperty,userCode },
157                                 { OPUserEntity.PasswordProperty,userPwd },
158                                 { OPUserEntity.EnabledProperty,true },
159                             });
160                             return count > 0;
161                         }
162                     }
163                 }
164             }
165 
166             return false;
167         }
168 
169 
170     }
LoginUserManager
  • 組合類 RSA 加密實例
 1     /// <summary>
 2     /// RSA 加密應用實例
 3     /// </summary>
 4     public class RSAApply
 5     {
 6         readonly string xmlPublicKey;
 7         readonly string xmlPrivateKey;
 8         readonly RSACryption rSACryption;
 9         const string TIMESTAMPKEY = "RSAApply_timeStamp";
10 
11         /// <summary>
12         /// 追加時間戳情況下的有效天數 
13         /// </summary>
14         public int ValidityDays { get; internal set; }
15 
16         public RSAApply(string base64PublicKey, string base64PrivateKey)
17         {
18             this.xmlPublicKey = RSAKeyConvert.RSAPublicKeyBase64ToXml(base64PublicKey);
19             this.xmlPrivateKey = RSAKeyConvert.RSAPrivateKeyBase64ToXml(base64PrivateKey);
20             rSACryption = new RSACryption();
21         }
22 
23         /// <summary>
24         /// 獲取密文
25         /// </summary>
26         /// <returns></returns>
27         public string GetCiphertext(Dictionary<string, string> source, bool timestamp = false)
28         {
29             if (timestamp)
30             {
31                 source.Add(TIMESTAMPKEY, TimeHelper.GetTStamp());
32             }
33             var sourceStr = JsonConvert.SerializeObject(source, Formatting.Indented);
34             var ciphertext = rSACryption.RSAEncrypt(xmlPublicKey, sourceStr);
35             return ciphertext;
36         }
37 
38         /// <summary>
39         /// 獲取明文
40         /// </summary>
41         /// <returns></returns>
42         public bool TryGetSource(string cipertext, ref Dictionary<string, string> source)
43         {
44             var sourceStr = rSACryption.RSADecrypt(xmlPrivateKey, cipertext);
45             source = JsonConvert.DeserializeObject<Dictionary<string, string>>(sourceStr);
46 
47             if (source.TryGetValue(TIMESTAMPKEY, out string timeStemp))
48             {
49                 if ((DateTime.Now - long.Parse(timeStemp).ToTimeStamp()).TotalDays > ValidityDays)
50                 {
51                     return false;
52                 }
53                 source.Remove(TIMESTAMPKEY);
54             }
55             return true;
56         }
57     }
RSAApply
  •  RSA 加密幫助類
  1 public class RSACryption
  2     {
  3 
  4         #region 私有屬性
  5 
  6         private Encoding rsaEncoding
  7         {
  8             get
  9             {
 10                 return Encoding.Unicode;
 11             }
 12         }
 13 
 14         private Encoding hashEncoding
 15         {
 16             get
 17             {
 18                 return Encoding.UTF8;
 19             }
 20         }
 21 
 22         #endregion
 23 
 24         #region RSA 加密解密
 25 
 26         #region RSA 的密鑰產生
 27 
 28         /// <summary>  
 29         /// RSA產生密鑰  
 30         /// </summary>  
 31         /// <param name="xmlPrivateKey">私鑰</param>  
 32         /// <param name="xmlPublicKey">公鑰</param>
 33         /// <returns></returns>
 34         public bool RSACreateKey(out string xmlPrivateKey, out string xmlPublicKey)
 35         {
 36             try
 37             {
 38                 var rsaProvider = new RSACryptoServiceProvider(1024);
 39                 xmlPrivateKey = rsaProvider.ToXmlString(true);
 40                 xmlPublicKey = rsaProvider.ToXmlString(false);
 41                 return true;
 42             }
 43             catch (Exception)
 44             {
 45                 xmlPrivateKey = string.Empty;
 46                 xmlPublicKey = string.Empty;
 47                 return false;
 48             }
 49         }
 50 
 51         #endregion
 52 
 53         #region RSA加密函數
 54 
 55         /// <summary>
 56         /// RSA 加密
 57         ///   首先對原始字符串做MD5哈希,然后再對哈希值加密。
 58         /// </summary>
 59         /// <param name="publicKeyBase64String"></param>
 60         /// <param name="source"></param>
 61         /// <returns></returns>
 62         public string RSAEncryption(string publicKeyBase64String, string source)
 63         {
 64             string hashValue = string.Empty;
 65             this.ComputeMD5Hash(source, ref hashValue);
 66             var pck = RSAKeyConvert.RSAPublicKeyBase64ToXml(publicKeyBase64String);
 67             var ciphertext = this.RSAEncrypt(pck, hashValue);
 68             return ciphertext;
 69         }
 70 
 71         /// <summary>  
 72         /// RSA的加密函數  
 73         /// </summary>  
 74         /// <param name="xmlPublicKey">公鑰</param>
 75         /// <param name="srouce">待加密文本</param>
 76         /// <returns></returns>
 77         public string RSAEncrypt(string xmlPublicKey, string srouce)
 78         {
 79             byte[] plainTextBytes = this.rsaEncoding.GetBytes(srouce);
 80             return this.RSAEncrypt(xmlPublicKey, plainTextBytes);
 81         }
 82 
 83         /// <summary>  
 84         /// RSA的加密函數   
 85         /// </summary>  
 86         /// <param name="xmlPublicKey">公鑰</param>  
 87         /// <param name="sourceBytes">加密后的字節數組</param>  
 88         /// <returns></returns>  
 89         public string RSAEncrypt(string xmlPublicKey, byte[] sourceBytes)
 90         {
 91             try
 92             {
 93                 byte[] cypherTextBytes;
 94                 string res = string.Empty;
 95                 var rsaProvider = new RSACryptoServiceProvider();
 96                 rsaProvider.FromXmlString(xmlPublicKey);
 97                 cypherTextBytes = rsaProvider.Encrypt(sourceBytes, false);
 98                 res = Convert.ToBase64String(cypherTextBytes);
 99                 return res;
100             }
101             catch (Exception) { return string.Empty; }
102         }
103 
104         #endregion
105 
106         #region RSA的解密函數
107 
108         /// <summary>  
109         /// RSA 解密
110         ///   解密失敗則返回空字符串
111         /// </summary>  
112         /// <param name="xmlPrivateKey">XML格式的私鑰</param>  
113         /// <param name="encryptString">加密后的字符串</param>  
114         /// <returns>解密后的字符串</returns>  
115         public string RSADecrypt(string xmlPrivateKey, string encryptString)
116         {
117             byte[] encryptBytes = Convert.FromBase64String(encryptString);
118             return this.RSADecrypt(xmlPrivateKey, encryptBytes);
119         }
120 
121         /// <summary>  
122         /// RSA 解密
123         ///   解密失敗則返回空字符串
124         /// </summary>  
125         /// <param name="xmlPrivateKey">XML格式的私鑰</param>  
126         /// <param name="encryptBytes">加密后的字節數組</param>  
127         /// <returns>解密后的字符串</returns>
128         public string RSADecrypt(string xmlPrivateKey, byte[] encryptBytes)
129         {
130             try
131             {
132                 var rsaProvider = new RSACryptoServiceProvider();
133                 rsaProvider.FromXmlString(xmlPrivateKey);
134                 byte[] dypherTextBytes = rsaProvider.Decrypt(encryptBytes, false);
135                 string res = this.rsaEncoding.GetString(dypherTextBytes);
136                 return res;
137             }
138             catch (Exception) { return string.Empty; }
139         }
140 
141         #endregion
142 
143         #endregion
144 
145         #region RSA數字簽名
146 
147         #region MD5 Hash
148 
149         /// <summary>  
150         /// 計算Hash(MD5)
151         /// </summary>  
152         /// <param name="sourceString">原始字符串</param>  
153         /// <param name="hashString">Hash值</param>  
154         /// <returns>是否成功</returns>  
155         public bool ComputeMD5Hash(string sourceString, ref string hashString)
156         {
157             byte[] hashBytes = new byte[0];
158             var res = this.ComputeMD5Hash(sourceString, ref hashBytes);
159             hashString = Convert.ToBase64String(hashBytes);
160             return res;
161         }
162 
163         /// <summary>  
164         /// 計算Hash(MD5)
165         /// </summary>  
166         /// <param name="srourceString">原始字符串</param>  
167         /// <param name="hashBytes">Hash值</param>  
168         /// <returns>是否成功</returns>  
169         public bool ComputeMD5Hash(string srourceString, ref byte[] hashBytes)
170         {
171             try
172             {
173                 var md5Provider = HashAlgorithm.Create("MD5");
174                 byte[] buffer = this.hashEncoding.GetBytes(srourceString);
175                 hashBytes = md5Provider.ComputeHash(buffer);
176                 return true;
177             }
178             catch (Exception) { return false; }
179         }
180 
181         #endregion
182 
183         #region RSA 創建簽名
184 
185         /// <summary>  
186         /// 生成RSA簽名
187         ///   簽名算法:MD5
188         /// </summary>  
189         /// <param name="xmlPrivateKey">XML私鑰</param>  
190         /// <param name="hashString">待簽名Hash值</param>  
191         /// <param name="signatureString">簽名的值</param>  
192         /// <returns>是否成功</returns>  
193         public bool CreateSignature(string xmlPrivateKey, string hashString, ref string signatureString)
194         {
195             byte[] hashBytes = Convert.FromBase64String(hashString);
196             var signatureBytes = new byte[0];
197             var res = this.CreateSignature(xmlPrivateKey, hashBytes, ref signatureBytes);
198             signatureString = Convert.ToBase64String(signatureBytes);
199             return res;
200         }
201 
202         /// <summary>  
203         /// 生成RSA簽名
204         ///   簽名算法:MD5
205         /// </summary>  
206         /// <param name="xmlPrivateKey">XML私鑰</param>  
207         /// <param name="hashBytes">待簽名Hash值</param>  
208         /// <param name="signatureString">簽名的值</param>  
209         /// <returns>是否成功</returns>  
210         public bool CreateSignature(string xmlPrivateKey, byte[] hashBytes, ref string signatureString)
211         {
212             var signatureBytes = new byte[0];
213             var res = this.CreateSignature(xmlPrivateKey, hashBytes, ref signatureBytes);
214             signatureString = Convert.ToBase64String(signatureBytes);
215             return res;
216         }
217 
218         /// <summary>  
219         /// 生成RSA簽名
220         ///   簽名算法:MD5
221         /// </summary>  
222         /// <param name="xmlPrivateKey">XML私鑰</param>  
223         /// <param name="hashString">待簽名Hash值</param>  
224         /// <param name="signatureBytes">簽名的值</param>
225         /// <returns>是否成功</returns>  
226         public bool CreateSignature(string xmlPrivateKey, string hashString, ref byte[] signatureBytes)
227         {
228             byte[] hashBytes = Convert.FromBase64String(hashString);
229             return this.CreateSignature(xmlPrivateKey, hashBytes, ref signatureBytes);
230         }
231 
232         /// <summary>  
233         /// 生成RSA簽名
234         ///   簽名算法:MD5
235         /// </summary>
236         /// <param name="xmlPrivateKey">XML私鑰</param>  
237         /// <param name="hashBytes">待驗證的Hash值</param>  
238         /// <param name="signatureBytes">簽名的值</param>  
239         /// <returns>是否成功</returns>  
240         public bool CreateSignature(string xmlPrivateKey, byte[] hashBytes, ref byte[] signatureBytes)
241         {
242             try
243             {
244                 var rsaProvider = new RSACryptoServiceProvider();
245 
246                 rsaProvider.FromXmlString(xmlPrivateKey);
247                 var rsaFormatter = new RSAPKCS1SignatureFormatter(rsaProvider);
248                 //設置算法
249                 rsaFormatter.SetHashAlgorithm("MD5");
250                 //執行簽名   
251                 signatureBytes = rsaFormatter.CreateSignature(hashBytes);
252                 return true;
253             }
254             catch (Exception) { return false; }
255         }
256 
257         #endregion
258 
259         #region RSA 驗證簽名
260 
261         /// <summary>  
262         /// 驗證RSA簽名  
263         /// </summary>  
264         /// <param name="xmlPublicKey">XML公鑰</param>  
265         /// <param name="hashString">待驗證的Hash值</param>  
266         /// <param name="signatureString">簽名的值</param>  
267         /// <returns></returns>  
268         public bool VerifySignature(string xmlPublicKey, string hashString, string signatureString)
269         {
270             byte[] signatureBytes = Convert.FromBase64String(signatureString);
271             byte[] hashBytes = Convert.FromBase64String(hashString);
272             return this.VerifySignature(xmlPublicKey, hashBytes, signatureBytes);
273         }
274 
275         /// <summary>  
276         /// 驗證RSA簽名  
277         /// </summary>  
278         /// <param name="xmlPublicKey">XML公鑰</param>  
279         /// <param name="hashBytes">待驗證的Hash值</param>  
280         /// <param name="signatureString">簽名的值</param>  
281         /// <returns></returns>  
282         public bool VerifySignature(string xmlPublicKey, byte[] hashBytes, string signatureString)
283         {
284             byte[] signatureBytes = Convert.FromBase64String(signatureString);
285             return this.VerifySignature(xmlPublicKey, hashBytes, signatureBytes);
286         }
287 
288         /// <summary>  
289         /// 驗證RSA簽名  
290         /// </summary>  
291         /// <param name="xmlPublicKey">XML公鑰</param>  
292         /// <param name="hashString">待驗證的Hash值</param>  
293         /// <param name="signatureBytes">簽名的值</param>  
294         /// <returns>驗簽結果</returns>  
295         public bool VerifySignature(string xmlPublicKey, string hashString, byte[] signatureBytes)
296         {
297             byte[] hashBytes = Convert.FromBase64String(hashString);
298             return this.VerifySignature(xmlPublicKey, hashBytes, signatureBytes);
299         }
300 
301         /// <summary>  
302         /// 驗證RSA簽名
303         /// </summary>  
304         /// <param name="xmlPublicKey">XML公鑰</param>  
305         /// <param name="hashBytes">待驗證的Hash值</param>  
306         /// <param name="signatureBytes">簽名的值</param>  
307         /// <returns>驗簽結果</returns>  
308         public bool VerifySignature(string xmlPublicKey, byte[] hashBytes, byte[] signatureBytes)
309         {
310             try
311             {
312                 var rsaProvider = new RSACryptoServiceProvider();
313                 rsaProvider.FromXmlString(xmlPublicKey);
314                 var rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsaProvider);
315                 //指定解密的時候HASH算法為MD5   
316                 rsaDeformatter.SetHashAlgorithm("MD5");
317                 if (rsaDeformatter.VerifySignature(hashBytes, signatureBytes))
318                 {
319                     return true;
320                 }
321                 else
322                 {
323                     return false;
324                 }
325             }
326             catch (Exception) { return false; }
327         }
328 
329         #endregion
330 
331         #endregion
332 
333     }
RSACryption
  •  RSA 密鑰格式轉換類
 1     /// <summary>
 2     /// RSA密鑰格式轉換
 3     /// </summary>
 4     public class RSAKeyConvert
 5     {
 6 
 7         #region 私鑰轉換
 8 
 9         /// <summary>    
10         /// RSA私鑰 Base64 To XML
11         /// </summary>    
12         /// <param name="privateKey">Base64格式的私鑰</param>    
13         /// <returns></returns>   
14         public static string RSAPrivateKeyBase64ToXml(string privateKey)
15         {
16             var privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));
17             return
18                 string.Format(
19                     "<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",
20                     Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),
21                     Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
22                     Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
23                     Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
24                     Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
25                     Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
26                     Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
27                     Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
28         }
29 
30         /// <summary>    
31         /// RSA私鑰 XML To Base64
32         /// </summary>    
33         /// <param name="privateKey">XML格式的私鑰</param>    
34         /// <returns></returns>   
35         public static string RSAPrivateKeyXmlToBase64(string privateKey)
36         {
37             XmlDocument doc = new XmlDocument();
38             doc.LoadXml(privateKey);
39             BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
40             BigInteger exp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
41             BigInteger d = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[0].InnerText));
42             BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[0].InnerText));
43             BigInteger q = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[0].InnerText));
44             BigInteger dp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[0].InnerText));
45             BigInteger dq = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[0].InnerText));
46             BigInteger qinv = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[0].InnerText));
47             RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv);
48             PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
49             byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
50             return Convert.ToBase64String(serializedPrivateBytes);
51         }
52 
53         #endregion
54 
55         #region 公鑰轉換
56 
57         /// <summary>    
58         /// RSA公鑰 Base64 To XML
59         /// </summary>    
60         /// <param name="publicKey">Base64格式的公鑰</param>    
61         /// <returns></returns>    
62         public static string RSAPublicKeyBase64ToXml(string publicKey)
63         {
64             RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
65             return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
66                 Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
67                 Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
68         }
69 
70         /// <summary>    
71         /// RSA公鑰 XML To Base64
72         /// </summary>    
73         /// <param name="publicKey">XML格式的公鑰</param>    
74         /// <returns></returns>   
75         public static string RSAPublicKeyXmlToBase64(string publicKey)
76         {
77             XmlDocument doc = new XmlDocument();
78             doc.LoadXml(publicKey);
79             BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
80             BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
81             RsaKeyParameters pub = new RsaKeyParameters(false, m, p);
82             SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);
83             byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
84             return Convert.ToBase64String(serializedPublicBytes);
85         }
86 
87         #endregion
88 
89     }
RSAKeyConvert
  •  mvc 過濾器
 1 public class APIAuthedAttribute : ActionFilterAttribute
 2     {
 3         public override void OnActionExecuting(HttpActionContext context)
 4         {
 5             base.OnActionExecuting(context);
 6             if (!LoginUserManager.CheckClientStatus(out Dictionary<string, string> user))
 7             {
 8                 context.Response = context.Request.CreateResponse<Result>(
 9                     HttpStatusCode.OK,
10                     new  
11                     {
12                         StatusCode = 1000,
13                         Message = "請先登錄",
14                         Success = false
15                     });
16             }
17         }
18     }
APIAuthedAttribute

     2、前台 

  •   添加 vuex 目錄結構。

  •   安裝 vuex 、js-cookie
npm install --save vuex js-cookie 
 1 // initial state
 2 // shape: [{ id, quantity }]
 3 import {AuthUser} from "../../api/api";
 4 import * as Cookies from "js-cookie"
 5 
 6 const state = {
 7     loginState: {
 8         loginIn: false,
 9         user: {
10             userName: ""
11         }
12     }
13 }
14 
15 // getters
16 const getters = {
17     userName: (state, getters, rootState) => {
18         if (state.loginState.loginIn) {
19             return state.loginState.user.userName
20         }
21     },
22     offLine: (state, getters, rootState) => {
23         return !state.loginState.loginIn;
24     }
25 }
26 
27 //actions
28 const actions = {
29     //從服務器端校驗本地登錄 Cookie 有效性
30     authUser({state, commit}) {
31         return  AuthUser().then(res => {
32             debugger;
33             if (res.Success) {
34                 commit('loginIn', {userName: res.Data.UserName});
35                 return true;
36             } else {
37                 commit('loginOut');
38                 return false;
39             }
40         });
41     }
42 }
43 
44 
45 // mutations
46 const mutations = {
47     //登入狀態
48     loginIn(state, user) {
49         state.loginState.loginIn = true;
50         state.loginState.user = user;
51         debugger;
52         Cookies.set('loginState', state.loginState, {expires: 1});
53     },
54     //登出狀態
55     loginOut(state) {
56         state.loginState.loginIn = false;
57         state.loginState.user = {};
58         Cookies.remove('loginState');
59     },
60     syncLoginState(state) {
61         debugger;
62         let cookieState = Cookies.getJSON('loginState');
63         if (cookieState) {
64             state.loginState = cookieState;
65         }
66     }
67 }
68 
69 export default {
70     namespaced: true,
71     state,
72     getters,
73     actions,
74     mutations
75 }
user.js
 1 import Vue from 'vue'
 2 import Vuex from 'vuex'
 3 import user from './modules/user'
 4 
 5 Vue.use(Vuex)
 6 
 7 const debug = process.env.NODE_ENV !== 'production'
 8 
 9 export default new Vuex.Store({
10     modules: {
11         user
12     },
13     strict: debug,
14     plugins:  []
15 })
index.js
  • 在入口函數添加用戶登陸狀態判斷 比如main.js
router.beforeEach((to, from, next) => {
    debugger;
    //離線用戶跳轉到首頁
    if (to.path != '/') {
        router.app.$store.commit('user/syncLoginState');
        if (router.app.$store.getters['user/offLine']) {

            //離線用戶鑒權,如果成功會自動登錄
            router.app.$store.dispatch('user/authUser').then((res) => {
                if (res) {
                    next();
                }else {
                    next({path: '/'});
                }
            });
            return;
        }
    }
    next();
});

就這些了,登入,登出等操作就不貼代碼了。

總結一下用到的點:

  1、vuex 的存儲源是一個自己定義的 state 對象,也就是說是腳本中一個 實例,它的作用域是當前頁面,如果再開一個瀏覽器標簽頁是取不到的。同理 localstorage 、 sessionStorage 也是一樣的。

  2、vuex actions 可以執行異步方法,可以返回 promise 。比如 請求api,執行 setTimeout ,使用  dispatch 調用,上面有例子。

  3、用新標簽頁請求一個路由時,代碼執行順序 router( vue 路由守護) => app .created( vue 根實例的  life hook ) => com(路由組件)。所以講用戶狀態判斷放到路由守衛里。

來源:

https://www.npmjs.com/package/js-cookie   

https://vuex.vuejs.org/zh/guide/actions.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM