所有需要账户登录的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

具体代码可以直接调用他们的子类像

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 = ; i < dataLength; i++)
{
if (i < keyLength)
{
dataBytes[i] ^= this.Key[i];
}
else
{
dataBytes[i] ^= this.Key[keyLength - ];
}
} return dataBytes;
} protected override byte[] DecryptImpl(byte[] dataBytes)
{
int dataLength = dataBytes.Length;
int IVLength = this.IV.Length; for (var i = ; i < dataLength; i++)
{
if (i < IVLength)
{
dataBytes[i] ^= this.IV[i];
}
else
{
dataBytes[i] ^= this.IV[IVLength - ];
}
} 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[];
var read = input.Read(buffer, , buffer.Length);
while (read > )
{
cryptStream.Write(buffer, , read);
read = input.Read(buffer, , 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[];
var read = cryptStream.Read(buffer, , buffer.Length);
while (read > )
{
output.Write(buffer, , read);
read = cryptStream.Read(buffer, , 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形式就可以表示成

ee11cbb19052e40b07aac0ca060c23ee=EgkCFnUaFlI

5f4dcc3b5aa765d61d8327deb882cf99=vDwCZGvezDfudh91hRsiow

欢迎访问我的个人网站 51zhang.net 网站还在不断开发中…

保存登录信息的Cookie加密技术的更多相关文章

  1. asp.net下使用Cookie保存登录信息

    在网页中登录窗口是最常见的,如果把登录信息存在客户机Cookie中,下次用户登录时,网页先在客户机上查找登录信息,如果成功即可跳过登录步骤直接到主窗口,如登录界面如下:

  2. .NET跨平台之旅:ASP.NET Core从传统ASP.NET的Cookie中读取用户登录信息

    在解决了asp.net core中访问memcached缓存的问题后,我们开始大踏步地向.net core进军——将更多站点向asp.net core迁移,在迁移涉及获取用户登录信息的站点时,我们遇到 ...

  3. Andriod中WebView加载登录界面获取Cookie信息并同步保存,使第二次不用登录也可查看个人信息。

    Android使用WebView加载登录的html界面,则通过登录成功获取Cookie并同步,可以是下一次不用登录也可以查看到个人信息,注:如果初始化加载登录,可通过缓存Cookie信息来验证是否要加 ...

  4. php使用session来保存用户登录信息

    php使用session来保存用户登录信息 使用session保存页面登录信息 1.数据库连接配置页面:connectvars.php <?php //数据库的位置 define('DB_HOS ...

  5. cookie保存登录的用户名和密码

    用cookie保存登录的用户名和密码,当用户访问网站的时候,获取cookie的用户名和密码,通过用 用cookie保存登录的用户名和密码,当用户访问网站的时候,获取cookie的用户名和密码,通过用户 ...

  6. 细讲前端设置cookie, 储存用户登录信息

    细讲前端设置cookie 引言 正文 一.设置cookie 二.查看cookie 三.删除cookie 四.封装cookie操作 结束语 引言 我们都知道如果想做一个用户登录并使浏览器保存其登录信息, ...

  7. spring boot:用cookie保存i18n信息避免每次请求时传递参数(spring boot 2.3.3)

    一,用cookie保存i18n信息的优点? 当开发一个web项目(非api站)时,如果把i18n的选择信息保存到cookie, 则不需要在每次发送请求时都传递所选择语言的参数, 也不需要增加heade ...

  8. 微信小程序 获取用户信息并保存登录状态

    微信小程序 获取用户信息并保存登录状态:http://www.360doc.com/content/18/0124/11/9200790_724662071.shtml

  9. 如何综合运用对称加密技术、非对称加密技术(公钥密码体制)和Hash函数 保证信息的保密性、完整性、可用性和不可否认性?

    一.几个问题 在提出问题之前,先创建一个使用场景,发送方(甲方)要给接收方(乙方)发送投标书.大家知道,投标书都包括发送方的标的,这个标的是不能被竞标者知晓,更不能被竞标者修改的.在传输的投标书时,提 ...

随机推荐

  1. Django 源码小剖: 响应数据 response 的返回

    响应数据的返回 在 WSGIHandler.__call__(self, environ, start_response) 方法调用了 WSGIHandler.get_response() 方法, 由 ...

  2. Spring3系列2 -- 松耦合的实现

    Spring3系列2 -- 松耦合的实现 一.      环境 spring-framework-3.2.4.RELEASE jdk1.7.0_11 Maven3.0.5 eclipse-jee-ju ...

  3. SAP ECC MM 配置文档

    SAP ECC 6.0 Configuration Document Materials Management (MM) Table of Content TOC \o \h \z 1. Genera ...

  4. Android之NDK开发

    转自:http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支持C ...

  5. 彻底解决Google浏览器CSS居中问题

    div做的界面时,又出现CSS hack(CSS兼容浏览器问题)在IE内核浏览器或者firefox浏览器中都能居中,没有居中的可以用其特殊标签来设定居中,如下划线 _ IE6优先识别,!importa ...

  6. 最近想上游戏,弄了个工作室,名"柑谷工作室"

    最近想上游戏,弄了个工作室,名"柑谷工作室",名字取得有点随便,原因是好名字都让狗用了.想当年我用的龙纹工作室,现在龙纹两字也被人用了.人家有硅谷,然后我弄个柑谷,差不多吧.算了, ...

  7. EDM备忘录:触发式邮件订阅和退订功能介绍

    一般来说,有触发式邮件订阅和退订功能是邮件模板设计中必不可少的两项功能,下面博主为大家介绍一下. 若客户在订阅后不想再收到这类邮件即可选择退订,将不再收到该IP地址的推广邮件,避免客户在继续收到这类邮 ...

  8. EFW框架问题收集与答疑

    回<[开源]EFW框架系列文章索引>        EFW框架源代码下载V1.3:http://pan.baidu.com/s/1c0dADO0 EFW框架实例源代码下载:http://p ...

  9. ecslipe cdt lib link

    项目属性-> settings -> mingw c linker 1.libs search 填写lib路径 2.lib 填写文件名,不要后缀

  10. Struts2知多少(2) Struts2 是什么

    Struts2是流行和成熟的基于MVC设计模式的Web应用程序框架. Struts2不只是Struts1下一个版本,它是一个完全重写的Struts架构. WebWork框架开始以Struts框架为基础 ...