Vue、Vuex+Cookie 实现自动登陆 。

时间:2024-03-07 20:02:44

概述

  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