https://www.cnblogs.com/VectorZhang/p/5425283.html
保存登录信息的Cookie加密技术
所有需要账户登录的website 基本都会想到这样一个问题, 如何保持用户在一定时间内登录有效。
最近本人就在项目中遇到这样的需求,某些页面只能Admin账户登录后访问, 当登录Admin账户后如何才能保持登录信息呢?
用Cookie或者Session来保存登录信息已经是一种比较成熟的技术。但是对于账户信息如果把明文放在Cookie里面显然是非常危险的。
今天给大家分享一下自己在项目中用到的一些加密解密技术。
Cookie 是以key-value的形式存数据。对于账户信息而言最简单的是 UserName 和 Password
如果以明文的形式放到Cookie 比如
UserName=fakeUser
Password=fakePsd
考虑到安全性的问题,显然没有任何website会这样做。
那么是否可以把这几个字段都加密呢?
对 Key 的加密
对key字段像UserName, Password只需要在Server端加密并保存即可,甚至都无需还原成明文。
复制代码
public static string MD5Hash(string
input)
{
byte[] data = Encoding.UTF8.GetBytes(input.Trim().ToLowerInvariant());
using (var md5 = new MD5CryptoServiceProvider())
{
data = md5.ComputeHash(data);
}
var ret = new StringBuilder();
foreach (byte b in data)
{
ret.Append(b.ToString("x2").ToLowerInvariant());
}
return ret.ToString();
}
复制代码
例如计算出UserName 和 Password的 MD5 hash 值,Cookie形式就可以表示成
ee11cbb19052e40b07aac0ca060c23ee=fakeUser
5f4dcc3b5aa765d61d8327deb882cf99=fakePsd
相比没有加密前安全性是不是高了那么一点点,但这肯定还是不够。我们最终的目标是对所有字段加密。
对Value的加密
对value字段加密就不能是单向的,试想一下如果在Server端对用户名加密放到Cookie再传到Client端, 看起来OK. 当Client端的cookie再传回Server端时,如果不能解密Encode后的用户名那么Cookie就等于失效了。
一个非常简单的算法就是用过异或来实现加密解密,比如提供一个秘钥 X,
encode_data = data ^ X
decode_data = encode_data ^ X
则 data == decode_data.
目前 .NET 提供不了不少对称加密算法都直接以dll 的形式给出了。.NET 中提供的对称加密算法都继承基类SymmetricAlgorithm
image
具体代码可以直接调用他们的子类像
TripleDESCryptoServiceProvider
RijndaelManaged
MSDN 上已经提供了的代码案例,这里就不再给出Test Sample.
为了能够灵活的运用到项目中本人就封装了一些接口
复制代码
// 定义加密解密的接口
public interface IEncryptionProvider
{
byte[] Key { get; }
byte[] IV { get; }
Encoding Encoding { get; }
string Encrypt(string data);
string Decrypt(string encodeData);
}
复制代码
复制代码
//加密解密抽象基类
public abstract class BaseEncryptionProvider : IEncryptionProvider
{
protected byte[] _keyBytes;
protected byte[] _IVBytes;
public byte[] Key
{
get
{
if (this._keyBytes == null)
{
this.GenerateKeyIV();
}
return this._keyBytes;
}
}
public byte[] IV
{
get
{
if (this._IVBytes == null)
{
this.GenerateKeyIV();
}
return this._IVBytes;
}
}
private Encoding _encoding;
public Encoding Encoding
{
get { return this._encoding ?? Encoding.UTF8; }
set { this._encoding = value; }
}
public string Encrypt(string data)
{
if (string.IsNullOrEmpty(data))
{
throw new ArgumentNullException("data");
}
byte[] bytes = this.Encoding.GetBytes(data);
var encodedBytes = this.EncryptImpl(bytes);
return this.PostEncrypt(encodedBytes);
}
public string Decrypt(string encodeData)
{
if (string.IsNullOrEmpty(encodeData))
{
throw new ArgumentNullException("encodeData");
}
var bytes = this.PreDecrypt(encodeData);
var decodeBytes = this.DecryptImpl(bytes);
return this.Encoding.GetString(decodeBytes);
}
//加密算法的实现函数
protected abstract byte[] EncryptImpl(byte[] bytes);
//解密算法的实现函数
protected abstract byte[] DecryptImpl(byte[] bytes);
public virtual string PostEncrypt(byte[] bytes)
{
return System.Convert.ToBase64String(bytes);
}
public virtual byte[] PreDecrypt(string input)
{
return System.Convert.FromBase64String(input);
}
public abstract void GenerateKeyIV();
}
复制代码
复制代码
//异或加密算法类
public class EOREncryptionProvider : BaseEncryptionProvider
{
private string _key;
public EOREncryptionProvider(string key)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException("key");
}
this._key = key;
}
public override void GenerateKeyIV()
{
this._keyBytes = this.Encoding.GetBytes(this._key);
this._IVBytes = this.Encoding.GetBytes(this._key);
}
//考虑到秘钥长度以及数据长度等因素 具体实现算法多种多样
protected override byte[] EncryptImpl(byte[] dataBytes)
{
int dataLength = dataBytes.Length;
int keyLength = this.Key.Length;
for (var i = 0; i < dataLength; i++)
{
if (i < keyLength)
{
dataBytes[i] ^= this.Key[i];
}
else
{
dataBytes[i] ^= this.Key[keyLength - 1];
}
}
return dataBytes;
}
protected override byte[] DecryptImpl(byte[] dataBytes)
{
int dataLength = dataBytes.Length;
int IVLength = this.IV.Length;
for (var i = 0; i < dataLength; i++)
{
if (i < IVLength)
{
dataBytes[i] ^= this.IV[i];
}
else
{
dataBytes[i] ^= this.IV[IVLength - 1];
}
}
return dataBytes;
}
}
复制代码
复制代码
// .Net 内置加密算法的封装
public class SymmetricAlgoEncryptionProvider : BaseEncryptionProvider
{
private SymmetricAlgorithm _symmetricAlgorithm;
public SymmetricAlgoEncryptionProvider(SymmetricAlgorithm providerImpl)
{
if (providerImpl == null)
{
throw new ArgumentNullException("providerImpl");
}
this._symmetricAlgorithm = providerImpl;
this._symmetricAlgorithm.Padding = PaddingMode.ISO10126;
}
protected override byte[] EncryptImpl(byte[] bytes)
{
byte[] encryptedData;
using (var input = new MemoryStream(bytes))
using (var output = new MemoryStream())
{
var encryptor = this._symmetricAlgorithm.CreateEncryptor(this.Key, this.IV);
using (var cryptStream = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
{
var buffer = new byte[1024];
var read = input.Read(buffer, 0, buffer.Length);
while (read > 0)
{
cryptStream.Write(buffer, 0, read);
read = input.Read(buffer, 0, buffer.Length);
}
cryptStream.FlushFinalBlock();
encryptedData = output.ToArray();
}
}
return encryptedData;
}
protected override byte[] DecryptImpl(byte[] bytes)
{
byte[] result;
using (var input = new MemoryStream(bytes))
using (var output = new MemoryStream())
{
var decryptor = this._symmetricAlgorithm.CreateDecryptor(this.Key, this.IV);
using (var cryptStream = new CryptoStream(input, decryptor, CryptoStreamMode.Read))
{
var buffer = new byte[1024];
var read = cryptStream.Read(buffer, 0, buffer.Length);
while (read > 0)
{
output.Write(buffer, 0, read);
read = cryptStream.Read(buffer, 0, buffer.Length);
}
cryptStream.Flush();
result = output.ToArray();
}
}
return result;
}
public override void GenerateKeyIV()
{
this._symmetricAlgorithm.GenerateKey();
this._symmetricAlgorithm.GenerateIV();
this._keyBytes = this._symmetricAlgorithm.Key;
this._IVBytes = this._symmetricAlgorithm.IV;
}
}
复制代码
最后可以这样调用
复制代码
static void Main(string[] args)
{
IEncryptionProvider provider = new EOREncryptionProvider("this is the key");
string data = "fakeUser";
string encodeData = provider.Encrypt(data);
Console.WriteLine("encodeData:{0}", encodeData);
string decodeData = provider.Decrypt(encodeData);
Console.WriteLine("decodeData:{0}", decodeData);
provider = new SymmetricAlgoEncryptionProvider(new TripleDESCryptoServiceProvider());
encodeData = provider.Encrypt(data);
Console.WriteLine("encodeData:{0}", encodeData);
decodeData = provider.Decrypt(encodeData);
Console.WriteLine("decodeData:{0}", decodeData);
}
复制代码
本文探讨了网站如何通过Cookie或Session保存登录信息,同时确保账户安全。介绍了使用MD5哈希和对称加密算法如TripleDES、Rijndael对Cookie中的用户名和密码进行加密的方法。
744

被折叠的 条评论
为什么被折叠?



