概述
1、自动登陆实现思路。
2、vuex + cookie 多标签页状态保持。
自动登陆的需求:
1、登陆时勾选自动登陆,退出登陆或登陆到期后再次登陆后自动填写表单(记住密码)或访问登陆页自动登陆。
2、安全性需求,cookie 的有效性判断应该放到服务端。
实现细节
1、后台:一个静态的登陆管理类 负责管理登陆用户,这里设计了两个 cookie 一个用来保存登陆信息、一个用来保存自动登陆信息。
登陆cookie 的有效时间是 30 分钟,自动登陆cookie 的有效时间是 3 天,分别保存了用户名、编码、密码;用户名、编码、密码、时间戳。
后台包含,RSA加密算法、cookie 管理、登陆相关业务(登入、登出、过滤器)。不干兴趣跳过,看前端代码。
/// <summary>
/// 登录用户管理
/// </summary>
public static class LoginUserManager
{
public const string DBENLOGININ = "DBEN.OP.LOGININ";
public const string DBENAUTOLOGIN = "DBEN.OP.AUTOLOGIN";
public const string DBENUSERCODE = "DBEN.OP.USERCODE";
public const string DBENUSERNAME = "DBEN.OP.USERNAME";
public const string DBENUSERPWD = "DBEN.OP.USERPASSWORD"; /// <summary>
/// RSA 加解密实例
/// </summary>
public static RSAApply RSAApply
{
get
{
return new RSAApply(
ConfigHelper.GetAppSetting("DBEN.StaticRSAPublicKey", @"MIGfM
A0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBRxFQos7Nc77goLB6cz2SM6Ae7OuuOTkycG2eyP
Lds7+hE8s6bqJMfdY6EOlPjGraATXSCsrPnowWeq2p59xyejJLlCfX3dE+Br5FuUG+MwK7K6i
HQ2lJLZlvnnmDqjmHO2+k14VOFwlXNOKkciWVsjT/mr4Xj4olG2gjOhWvqQIDAQAB"),
ConfigHelper.GetAppSetting("DBEN.StaticRSAPrivateKey", @"MIIC
dwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMFHEVCizs1zvuCgsHpzPZIzoB7s6
645OTJwbZ7I8t2zv6ETyzpuokx91joQ6U+MatoBNdIKys+ejBZ6rann3HJ6MkuUJ9fd0T4Gvk
W5Qb4zArsrqIdDaUktmW+eeYOqOYc7b6TXhU4XCVc04qRyJZWyNP+avhePiiUbaCM6Fa+pAgM
BAAECgYAePxDmnZPfcw2b+YmkoAQyrQGR1WHMkgfxbMa64pefOlHy0zYqnsWnUsoDrEHWwRK3
qxjRFf9HHnity+UBgddtjRrSW9ly+5zSvTTVb3wHfSqV/xJsakZ3M8MjVLCQXZarXTbRlYBnx
eFLcvvfouDHbefK6cqIpEk1uWllq7eNQQJBAOpWf2gsvGnFTU0vrx77Ed1QHH0C4ldss63N91
/YbrmNl9jQNcWD2DG3tw3ToSM8JIAb1Rdw9/kwpoqW9qp0mI8CQQDTJOWQum/+oovU7MZrgzR
K3N/wVXt4GIDgL4k48NSvzA+jRGf5MdphsqQKHuws9F4O+P7w/mK2QOHx4ys8OqBHAkEAnj6L
Cu4qzcJO0TDCMUmaZrkSg9jOv/rH2zabNj4Rh3v2bpMrvJWsCObm1o9y4Thb7abd31aKHdycm
joXmEPkQQJAW62hn/3TsxSQ8pr8bKJDil3tPkVfnv3Et5LsWjT3pH1OLO3+10y2LcWLRHm4wq
w4SvgCelF6OvhhIs4ob7Zk8QJBAIXEwsLcy9xZaRt85dIWuJFfbuAmCXiNWSJEhIFYPkLUvi2
QHZTdLHpSbi5oCPIVKw4CDTAP4b+JfGrrFaZjWNc="));
}
} /// <summary>
/// 已登录
/// </summary>
/// <param name="userCode"></param>
public static void SetLoginIn(string userCode, string userName, string userPassword)
{
var dic = new Dictionary<string, string>
{
{ DBENUSERCODE, userCode },
{ DBENUSERNAME, userName },
{ DBENUSERPWD, userPassword }
};
CookieManager.SetCookie(DBENLOGININ, RSAApply.GetCiphertext(dic, false));
} public static void SetLoginOut()
{
CookieManager.RemoveCookie(DBENLOGININ);
} /// <summary>
/// 自动登录
/// </summary>
/// <param name="userCode"></param>
public static void SetAutoLogin(string userCode, string userName, string userPassword)
{
if (CookieManager.GetCookie(DBENAUTOLOGIN) == null)
{
//首次勾选自动登录,创建自动登录的cookie。
var dic = new Dictionary<string, string>
{
{ DBENUSERCODE, userCode },
{ DBENUSERNAME, userName },
{ DBENUSERPWD, userPassword }
};
CookieManager.SetCookie(new HttpCookie(DBENAUTOLOGIN, RSAApply.GetCiphertext(dic, true)) { Expires = DateTime.Now.AddDays(RSAApply.ValidityDays) });
}
//通过自动登录也要设置已登录的 cookie
SetLoginIn(userCode, userName, userPassword);
} /// <summary>
/// 检查客户端状态
/// </summary>
/// <returns></returns>
public static bool CheckClientStatus(out Dictionary<string, string> user)
{
/****
* 如果存在 已登录 cookie 且译文有效,用户未被禁用,则返回true
* 否则检验 自动登录 cookie。
* 自动登录 cookie 存在且译文有效,自动登录后返回 true。
* */ var cookie = CookieManager.GetCookie(DBENLOGININ);
if (cookie != null)
{
return CheckCiphertext(cookie.Value, out user);
}
else
{
// 如果不是已登录,检查是否存在自动登录 cookie
cookie = CookieManager.GetCookie(DBENAUTOLOGIN);
if (cookie != null)
{
if (CheckCiphertext(cookie.Value, out user))
{
//将此用户设置为已登录
SetLoginIn(user[DBENUSERCODE], user[DBENUSERNAME], user[DBENUSERPWD]);
return true;
}
}
user = null;
return false;
}
} /// <summary>
/// 获取客户端用户信息
/// </summary>
/// <returns>返回一个从 cookie 创建的新实例</returns>
public static OPUserEntity GetClientUserInfo()
{
OPUserEntity res = null;
if (CheckClientStatus(out Dictionary<string, string> user))
{
res = new OPUserEntity
{
Code = user[DBENUSERCODE],
UserName = user[DBENUSERNAME],
Password = user[DBENUSERPWD]
};
}
return res;
} /// <summary>
/// 校验密文有效性,包括密文能否解密、账户有效性。
/// </summary>
/// <param name="ciphertext">密文</param>
/// <param name="user">如果返回值为方式则返回一个空实例</param>
/// <returns></returns>
private static bool CheckCiphertext(string ciphertext, out Dictionary<string, string> user)
{
user = new Dictionary<string, string>();
var repo = RF.ResolveInstance<OPUserEntityRepository>();
if (RSAApply.TryGetSource(ciphertext, ref user))
{
if (user.TryGetValue(DBENUSERCODE, out string userCode))
{
if (user.TryGetValue(DBENUSERPWD, out string userPwd))
{
if (user.TryGetValue(DBENUSERNAME, out string userName))
{
var count = repo.CountBy(new CommonQueryCriteria
{
{ OPUserEntity.UserNameProperty,userName },
{ OPUserEntity.CodeProperty,userCode },
{ OPUserEntity.PasswordProperty,userPwd },
{ OPUserEntity.EnabledProperty,true },
});
return count > ;
}
}
}
} return false;
} }
LoginUserManager
- 组合类 RSA 加密实例
/// <summary>
/// RSA 加密应用实例
/// </summary>
public class RSAApply
{
readonly string xmlPublicKey;
readonly string xmlPrivateKey;
readonly RSACryption rSACryption;
const string TIMESTAMPKEY = "RSAApply_timeStamp"; /// <summary>
/// 追加时间戳情况下的有效天数
/// </summary>
public int ValidityDays { get; internal set; } public RSAApply(string base64PublicKey, string base64PrivateKey)
{
this.xmlPublicKey = RSAKeyConvert.RSAPublicKeyBase64ToXml(base64PublicKey);
this.xmlPrivateKey = RSAKeyConvert.RSAPrivateKeyBase64ToXml(base64PrivateKey);
rSACryption = new RSACryption();
} /// <summary>
/// 获取密文
/// </summary>
/// <returns></returns>
public string GetCiphertext(Dictionary<string, string> source, bool timestamp = false)
{
if (timestamp)
{
source.Add(TIMESTAMPKEY, TimeHelper.GetTStamp());
}
var sourceStr = JsonConvert.SerializeObject(source, Formatting.Indented);
var ciphertext = rSACryption.RSAEncrypt(xmlPublicKey, sourceStr);
return ciphertext;
} /// <summary>
/// 获取明文
/// </summary>
/// <returns></returns>
public bool TryGetSource(string cipertext, ref Dictionary<string, string> source)
{
var sourceStr = rSACryption.RSADecrypt(xmlPrivateKey, cipertext);
source = JsonConvert.DeserializeObject<Dictionary<string, string>>(sourceStr); if (source.TryGetValue(TIMESTAMPKEY, out string timeStemp))
{
if ((DateTime.Now - long.Parse(timeStemp).ToTimeStamp()).TotalDays > ValidityDays)
{
return false;
}
source.Remove(TIMESTAMPKEY);
}
return true;
}
}
RSAApply
- RSA 加密帮助类
public class RSACryption
{ #region 私有属性 private Encoding rsaEncoding
{
get
{
return Encoding.Unicode;
}
} private Encoding hashEncoding
{
get
{
return Encoding.UTF8;
}
} #endregion #region RSA 加密解密 #region RSA 的密钥产生 /// <summary>
/// RSA产生密钥
/// </summary>
/// <param name="xmlPrivateKey">私钥</param>
/// <param name="xmlPublicKey">公钥</param>
/// <returns></returns>
public bool RSACreateKey(out string xmlPrivateKey, out string xmlPublicKey)
{
try
{
var rsaProvider = new RSACryptoServiceProvider();
xmlPrivateKey = rsaProvider.ToXmlString(true);
xmlPublicKey = rsaProvider.ToXmlString(false);
return true;
}
catch (Exception)
{
xmlPrivateKey = string.Empty;
xmlPublicKey = string.Empty;
return false;
}
} #endregion #region RSA加密函数 /// <summary>
/// RSA 加密
/// 首先对原始字符串做MD5哈希,然后再对哈希值加密。
/// </summary>
/// <param name="publicKeyBase64String"></param>
/// <param name="source"></param>
/// <returns></returns>
public string RSAEncryption(string publicKeyBase64String, string source)
{
string hashValue = string.Empty;
this.ComputeMD5Hash(source, ref hashValue);
var pck = RSAKeyConvert.RSAPublicKeyBase64ToXml(publicKeyBase64String);
var ciphertext = this.RSAEncrypt(pck, hashValue);
return ciphertext;
} /// <summary>
/// RSA的加密函数
/// </summary>
/// <param name="xmlPublicKey">公钥</param>
/// <param name="srouce">待加密文本</param>
/// <returns></returns>
public string RSAEncrypt(string xmlPublicKey, string srouce)
{
byte[] plainTextBytes = this.rsaEncoding.GetBytes(srouce);
return this.RSAEncrypt(xmlPublicKey, plainTextBytes);
} /// <summary>
/// RSA的加密函数
/// </summary>
/// <param name="xmlPublicKey">公钥</param>
/// <param name="sourceBytes">加密后的字节数组</param>
/// <returns></returns>
public string RSAEncrypt(string xmlPublicKey, byte[] sourceBytes)
{
try
{
byte[] cypherTextBytes;
string res = string.Empty;
var rsaProvider = new RSACryptoServiceProvider();
rsaProvider.FromXmlString(xmlPublicKey);
cypherTextBytes = rsaProvider.Encrypt(sourceBytes, false);
res = Convert.ToBase64String(cypherTextBytes);
return res;
}
catch (Exception) { return string.Empty; }
} #endregion #region RSA的解密函数 /// <summary>
/// RSA 解密
/// 解密失败则返回空字符串
/// </summary>
/// <param name="xmlPrivateKey">XML格式的私钥</param>
/// <param name="encryptString">加密后的字符串</param>
/// <returns>解密后的字符串</returns>
public string RSADecrypt(string xmlPrivateKey, string encryptString)
{
byte[] encryptBytes = Convert.FromBase64String(encryptString);
return this.RSADecrypt(xmlPrivateKey, encryptBytes);
} /// <summary>
/// RSA 解密
/// 解密失败则返回空字符串
/// </summary>
/// <param name="xmlPrivateKey">XML格式的私钥</param>
/// <param name="encryptBytes">加密后的字节数组</param>
/// <returns>解密后的字符串</returns>
public string RSADecrypt(string xmlPrivateKey, byte[] encryptBytes)
{
try
{
var rsaProvider = new RSACryptoServiceProvider();
rsaProvider.FromXmlString(xmlPrivateKey);
byte[] dypherTextBytes = rsaProvider.Decrypt(encryptBytes, false);
string res = this.rsaEncoding.GetString(dypherTextBytes);
return res;
}
catch (Exception) { return string.Empty; }
} #endregion #endregion #region RSA数字签名 #region MD5 Hash /// <summary>
/// 计算Hash(MD5)
/// </summary>
/// <param name="sourceString">原始字符串</param>
/// <param name="hashString">Hash值</param>
/// <returns>是否成功</returns>
public bool ComputeMD5Hash(string sourceString, ref string hashString)
{
byte[] hashBytes = new byte[];
var res = this.ComputeMD5Hash(sourceString, ref hashBytes);
hashString = Convert.ToBase64String(hashBytes);
return res;
} /// <summary>
/// 计算Hash(MD5)
/// </summary>
/// <param name="srourceString">原始字符串</param>
/// <param name="hashBytes">Hash值</param>
/// <returns>是否成功</returns>
public bool ComputeMD5Hash(string srourceString, ref byte[] hashBytes)
{
try
{
var md5Provider = HashAlgorithm.Create("MD5");
byte[] buffer = this.hashEncoding.GetBytes(srourceString);
hashBytes = md5Provider.ComputeHash(buffer);
return true;
}
catch (Exception) { return false; }
} #endregion #region RSA 创建签名 /// <summary>
/// 生成RSA签名
/// 签名算法:MD5
/// </summary>
/// <param name="xmlPrivateKey">XML私钥</param>
/// <param name="hashString">待签名Hash值</param>
/// <param name="signatureString">签名的值</param>
/// <returns>是否成功</returns>
public bool CreateSignature(string xmlPrivateKey, string hashString, ref string signatureString)
{
byte[] hashBytes = Convert.FromBase64String(hashString);
var signatureBytes = new byte[];
var res = this.CreateSignature(xmlPrivateKey, hashBytes, ref signatureBytes);
signatureString = Convert.ToBase64String(signatureBytes);
return res;
} /// <summary>
/// 生成RSA签名
/// 签名算法:MD5
/// </summary>
/// <param name="xmlPrivateKey">XML私钥</param>
/// <param name="hashBytes">待签名Hash值</param>
/// <param name="signatureString">签名的值</param>
/// <returns>是否成功</returns>
public bool CreateSignature(string xmlPrivateKey, byte[] hashBytes, ref string signatureString)
{
var signatureBytes = new byte[];
var res = this.CreateSignature(xmlPrivateKey, hashBytes, ref signatureBytes);
signatureString = Convert.ToBase64String(signatureBytes);
return res;
} /// <summary>
/// 生成RSA签名
/// 签名算法:MD5
/// </summary>
/// <param name="xmlPrivateKey">XML私钥</param>
/// <param name="hashString">待签名Hash值</param>
/// <param name="signatureBytes">签名的值</param>
/// <returns>是否成功</returns>
public bool CreateSignature(string xmlPrivateKey, string hashString, ref byte[] signatureBytes)
{
byte[] hashBytes = Convert.FromBase64String(hashString);
return this.CreateSignature(xmlPrivateKey, hashBytes, ref signatureBytes);
} /// <summary>
/// 生成RSA签名
/// 签名算法:MD5
/// </summary>
/// <param name="xmlPrivateKey">XML私钥</param>
/// <param name="hashBytes">待验证的Hash值</param>
/// <param name="signatureBytes">签名的值</param>
/// <returns>是否成功</returns>
public bool CreateSignature(string xmlPrivateKey, byte[] hashBytes, ref byte[] signatureBytes)
{
try
{
var rsaProvider = new RSACryptoServiceProvider(); rsaProvider.FromXmlString(xmlPrivateKey);
var rsaFormatter = new RSAPKCS1SignatureFormatter(rsaProvider);
//设置算法
rsaFormatter.SetHashAlgorithm("MD5");
//执行签名
signatureBytes = rsaFormatter.CreateSignature(hashBytes);
return true;
}
catch (Exception) { return false; }
} #endregion #region RSA 验证签名 /// <summary>
/// 验证RSA签名
/// </summary>
/// <param name="xmlPublicKey">XML公钥</param>
/// <param name="hashString">待验证的Hash值</param>
/// <param name="signatureString">签名的值</param>
/// <returns></returns>
public bool VerifySignature(string xmlPublicKey, string hashString, string signatureString)
{
byte[] signatureBytes = Convert.FromBase64String(signatureString);
byte[] hashBytes = Convert.FromBase64String(hashString);
return this.VerifySignature(xmlPublicKey, hashBytes, signatureBytes);
} /// <summary>
/// 验证RSA签名
/// </summary>
/// <param name="xmlPublicKey">XML公钥</param>
/// <param name="hashBytes">待验证的Hash值</param>
/// <param name="signatureString">签名的值</param>
/// <returns></returns>
public bool VerifySignature(string xmlPublicKey, byte[] hashBytes, string signatureString)
{
byte[] signatureBytes = Convert.FromBase64String(signatureString);
return this.VerifySignature(xmlPublicKey, hashBytes, signatureBytes);
} /// <summary>
/// 验证RSA签名
/// </summary>
/// <param name="xmlPublicKey">XML公钥</param>
/// <param name="hashString">待验证的Hash值</param>
/// <param name="signatureBytes">签名的值</param>
/// <returns>验签结果</returns>
public bool VerifySignature(string xmlPublicKey, string hashString, byte[] signatureBytes)
{
byte[] hashBytes = Convert.FromBase64String(hashString);
return this.VerifySignature(xmlPublicKey, hashBytes, signatureBytes);
} /// <summary>
/// 验证RSA签名
/// </summary>
/// <param name="xmlPublicKey">XML公钥</param>
/// <param name="hashBytes">待验证的Hash值</param>
/// <param name="signatureBytes">签名的值</param>
/// <returns>验签结果</returns>
public bool VerifySignature(string xmlPublicKey, byte[] hashBytes, byte[] signatureBytes)
{
try
{
var rsaProvider = new RSACryptoServiceProvider();
rsaProvider.FromXmlString(xmlPublicKey);
var rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsaProvider);
//指定解密的时候HASH算法为MD5
rsaDeformatter.SetHashAlgorithm("MD5");
if (rsaDeformatter.VerifySignature(hashBytes, signatureBytes))
{
return true;
}
else
{
return false;
}
}
catch (Exception) { return false; }
} #endregion #endregion }
RSACryption
- RSA 密钥格式转换类
/// <summary>
/// RSA密钥格式转换
/// </summary>
public class RSAKeyConvert
{ #region 私钥转换 /// <summary>
/// RSA私钥 Base64 To XML
/// </summary>
/// <param name="privateKey">Base64格式的私钥</param>
/// <returns></returns>
public static string RSAPrivateKeyBase64ToXml(string privateKey)
{
var privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));
return
string.Format(
"<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>",
Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
} /// <summary>
/// RSA私钥 XML To Base64
/// </summary>
/// <param name="privateKey">XML格式的私钥</param>
/// <returns></returns>
public static string RSAPrivateKeyXmlToBase64(string privateKey)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(privateKey);
BigInteger m = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[].InnerText));
BigInteger exp = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[].InnerText));
BigInteger d = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[].InnerText));
BigInteger p = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[].InnerText));
BigInteger q = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[].InnerText));
BigInteger dp = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[].InnerText));
BigInteger dq = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[].InnerText));
BigInteger qinv = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[].InnerText));
RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv);
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
return Convert.ToBase64String(serializedPrivateBytes);
} #endregion #region 公钥转换 /// <summary>
/// RSA公钥 Base64 To XML
/// </summary>
/// <param name="publicKey">Base64格式的公钥</param>
/// <returns></returns>
public static string RSAPublicKeyBase64ToXml(string publicKey)
{
RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
} /// <summary>
/// RSA公钥 XML To Base64
/// </summary>
/// <param name="publicKey">XML格式的公钥</param>
/// <returns></returns>
public static string RSAPublicKeyXmlToBase64(string publicKey)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(publicKey);
BigInteger m = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[].InnerText));
BigInteger p = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[].InnerText));
RsaKeyParameters pub = new RsaKeyParameters(false, m, p);
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);
byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
return Convert.ToBase64String(serializedPublicBytes);
} #endregion }
RSAKeyConvert
- mvc 过滤器
public class APIAuthedAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext context)
{
base.OnActionExecuting(context);
if (!LoginUserManager.CheckClientStatus(out Dictionary<string, string> user))
{
context.Response = context.Request.CreateResponse<Result>(
HttpStatusCode.OK,
new
{
StatusCode = ,
Message = "请先登录",
Success = false
});
}
}
}
APIAuthedAttribute
2、前台
- 添加 vuex 目录结构。
- 安装 vuex 、js-cookie
npm install --save vuex js-cookie
// initial state
// shape: [{ id, quantity }]
import {AuthUser} from "../../api/api";
import * as Cookies from "js-cookie" const state = {
loginState: {
loginIn: false,
user: {
userName: ""
}
}
} // getters
const getters = {
userName: (state, getters, rootState) => {
if (state.loginState.loginIn) {
return state.loginState.user.userName
}
},
offLine: (state, getters, rootState) => {
return !state.loginState.loginIn;
}
} //actions
const actions = {
//从服务器端校验本地登录 Cookie 有效性
authUser({state, commit}) {
return AuthUser().then(res => {
debugger;
if (res.Success) {
commit('loginIn', {userName: res.Data.UserName});
return true;
} else {
commit('loginOut');
return false;
}
});
}
} // mutations
const mutations = {
//登入状态
loginIn(state, user) {
state.loginState.loginIn = true;
state.loginState.user = user;
debugger;
Cookies.set('loginState', state.loginState, {expires: 1});
},
//登出状态
loginOut(state) {
state.loginState.loginIn = false;
state.loginState.user = {};
Cookies.remove('loginState');
},
syncLoginState(state) {
debugger;
let cookieState = Cookies.getJSON('loginState');
if (cookieState) {
state.loginState = cookieState;
}
}
} export default {
namespaced: true,
state,
getters,
actions,
mutations
}
user.js
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user' Vue.use(Vuex) const debug = process.env.NODE_ENV !== 'production' export default new Vuex.Store({
modules: {
user
},
strict: debug,
plugins: []
})
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
Vue、Vuex+Cookie 实现自动登陆 。的更多相关文章
-
ThinkPHP做自动登陆及异位或加密COOKIE!
异位或加密方法: /* *登陆如果自动登陆加密 *默认是0解密状态,1是加密 *采用的方法是异位或加密 */ function encrytion($value,$type=0){ $key = md ...
-
ASP.NET -- WebForm -- Cookie的使用 应用程序权限设计 权限设计文章汇总 asp.net后台管理系统-登陆模块-是否自动登陆 C# 读写文件摘要
ASP.NET -- WebForm -- Cookie的使用 ASP.NET -- WebForm -- Cookie的使用 Cookie是存在浏览器内存或磁盘上. 1. Test3.aspx文件 ...
-
PHP中Cookie的使用---添加/更新/删除/获取Cookie 及 自动填写该用户的用户名和密码和判断是否第一次登陆
PHP中Cookie的使用---添加/更新/删除/获取Cookie 及 自动填写该用户的用户名和密码和判断是否第一次登陆 什么是cookie 服务器在客户端保存用户的信息,比如登录名,密码等 这些数 ...
-
2017.11.23 利用Cookie管理实现自动登陆
Cookie管理 Cookie对象是由服务器产生并保存在客户端的信息,常用他记录用户个人信息以及个性化设置.用户每次访问网点时,应用程序就可以检索以前保存的信息 Cookie对象属于的类是javax. ...
-
Vue+Vuex实现自动登录 升级版
Vue+Vuex实现自动登录 升级版 之前实现的版本在这里:Vue+Vuex实现自动登录 在之前实现的版本中,如果你进行测试,可以看到在浏览器的local Storage中,确实里面有了我 ...
-
Vue+Vuex 实现自动登录功能
刚刚实现了Vue+Vuex的自动登录功能,在实现的时候遇到了一些问题,这里记录一下: 因为这个还不够完善,在写完下列代码后,又进行了补充,可以从https://www.cnblogs.com/xiao ...
-
curl模拟自动登陆&;采集网页数据
<!DOCTYPE> <html> <head> <meta http-equiv="Content-Type" content=&quo ...
-
java的web项目中使用cookie保存用户登陆信息
本文转自:http://lever0066.iteye.com/blog/1735963 最近在编写论坛系统的实现,其中就涉及到用户登陆后保持会话直到浏览器关闭,同时可以使用cookie保存登陆信息以 ...
-
让Ecshop网店系统用户自动登陆
让Ecshop网店系统用户户自动登陆,打开ecshop includes/init.php文件,可以发现Ecshop系统判断用户的SESSION不存在的时候会去读取存储在COOKIES里面的值.如下代 ...
随机推荐
-
ubuntu - 中文
首先要从Ubuntu语言设置那里,把中文语言包安装上 打开/etc/environment 在下面添加如下两行 LANG="zh_CN.UTF-8″ LANGUAGE="zh_CN ...
-
phpStorm支持CodeIgniter代码提示/自动完成
下载这个文件phpstorm-ci-ac 或者去github下载解压里面的三个文件到ci根目录下然后找到这三个文件 system\core\Controller.phpsystem\core\Mode ...
-
[读书笔记]设计原本[The Design of Design]
第1章 设计之命题 1.设计首先诞生于脑海里,再慢慢逐步成形(实现) 2.好的设计具有概念完整性:统一.经济.清晰.优雅.利落.漂亮... 第2章 工程师怎样进行设计思维——理性模型 1.有序模型的有 ...
-
log4j源码解析
前言:本文将在slf4j的基础上解释log4j的应用,阅读本文前可先行阅读SLF4J源码解析-LoggerFactory(二) 前言概要 在前言中提到的slf4j的基础,其主要是通过logback的a ...
-
unity3d ipv6支持
unity游戏应用提交app stroe需要通过ipv6测试,但是unity本身我没找到可用的接口,所以使用ios插件来处理. 插件的IOSNativeNet.h和IOSNativeNet.m代码: ...
-
PhpStorm服务激活
日期 服务地址 状态 2018-03-15 http://idea.singee77.com/ 使用中
-
Bresenham算法
1 算法原理 基本原理从某处摘得:设直线方程为yi+1=yi+k(xi+1-xi)+k.假设列坐标象素已经确定为xi,其行坐标为yi.那么下一个象素的列坐标为xi+1,而行坐标要么为yi,要么递增1为 ...
-
javascript 面向过程和面向对象
面向过程 思维方式:把解决问题的关注点,放到解决问题的每一个详细步骤上面. 面向对象 思维方式:把解决问题的关注点,放到解决问题需要的一些对象身上. 创建对象: 对象字面量 使用内置构造对象 封装简单 ...
-
poj 2031 给出每个结点的3维坐标 以及结点的半径 (MST)
3维空间中有N个圆球,给出x y z 以及圆球的半径 ,求最小生成树 边的权值为两个圆球间的距离 如果圆球相互接触 则权值为0 求最小的权值和 Sample Input 3 //n10.000 10. ...
-
log4js 2.X版本配置详解
const log4js = require('log4js'); log4js.configure({ appenders: { cheese: { type: 'file', filename: ...