家园志改版--登录验证加密处理
2009-12-24 15:44
387 查看
上一篇关于登录模块遗留下了加密问题。
开始的时候我认为即使要加密也没有多大意义,因为开始判断用户是否登录的方法只判断客户端是否有名为"UserName"和"UserID"的Cookie,如下代码:
所以,即使对Cookie加密也没有半点意义。但是我知道这样很不安全,只要客户端添加两个Cookie就可以登录了,岂不是很不安全。penpen的提议给了我思路:将同一个字段的用两种不同方法加密,判断时再各自解密并判断是否相等。具体流程如下图示意:
这样保存到客户端的Cookie是加过密的,很小的概率用户添加的Cookie值经过解密后会相等(但是还是有概率的)。
这里增加了三个条件说明用户未登录:解密后的UserName和UserEName不相等;解密后的UserID和UserEID不相等;客户端的Cookie少于必须的Cookie。然而在我测试的时候发现如果我将Cookie值改变成长度大于8的时候,程序就会报错,所以加上Try{}Catch{},当然此时用户肯定未登录。
由于篇幅的问题,这就不一一写出来了。可以下载源程序。
开始的时候我认为即使要加密也没有多大意义,因为开始判断用户是否登录的方法只判断客户端是否有名为"UserName"和"UserID"的Cookie,如下代码:
public static LoginState CheckLogin() { HttpCookieCollection CookieCollection = GetSavedCookieCollection(); if (CookieCollection.AllKeys.Length < keys.Length) { return LoginState.UnLogin; } else { return LoginState.Success; } } }
所以,即使对Cookie加密也没有半点意义。但是我知道这样很不安全,只要客户端添加两个Cookie就可以登录了,岂不是很不安全。penpen的提议给了我思路:将同一个字段的用两种不同方法加密,判断时再各自解密并判断是否相等。具体流程如下图示意:
改进后的代码:
保存Cookie的时候就要将UserID以两个不同密钥加密保存,UserName也是如此。现在保存到Cookie的值如下:private static string[] keys = { "UserID","UserEID", "UserName","UserEName" }; //需要存放在Cookie里面的信息
保存Cookie的方法如下:
public static void SaveCookie(bool saveLong, string username) { int userid = GetUserIDByUserName(username); if (userid != -1) { Hashtable CookieValues = new Hashtable(); CookieValues["UserID"] = Encryptor.Encrypt(userid.ToString()); CookieValues["UserEID"] = Encryptor.Encrypt(userid.ToString(), "7E52PDK9"); CookieValues["UserName"] =Encryptor.Encrypt( username); CookieValues["UserEName"] = Encryptor.Encrypt(username, "7E52PDK9"); HttpCookieCollection cookieCollection = GetCookieCollection(); foreach (string key in keys) { cookieCollection[key].Value = CookieValues[key].ToString(); if (saveLong) { //如果用户要求记住密码,则让Cookie在14天后过期 cookieCollection[key].Expires = DateTime.Now.AddDays(14d); } HttpContext.Current.Response.Cookies.Add(cookieCollection[key]); } } }
这样保存到客户端的Cookie是加过密的,很小的概率用户添加的Cookie值经过解密后会相等(但是还是有概率的)。
现在需要改进判断用户是否已登录的方法,
public static LoginState CheckLogin() { HttpCookieCollection CookieCollection = GetSavedCookieCollection(); //7E52PDK9 try { if (CookieCollection.AllKeys.Length < keys.Length || Encryptor.Decrypt(CookieCollection["UserID"].Value) != Encryptor.Decrypt(CookieCollection["UserEID"].Value, "7E52PDK9") || Encryptor.Decrypt(CookieCollection["UserName"].Value) != Encryptor.Decrypt(CookieCollection["UserEName"].Value, "7E52PDK9")) { return LoginState.UnLogin; } else { return LoginState.Success; } } catch (Exception) { return LoginState.UnLogin; } }
这里增加了三个条件说明用户未登录:解密后的UserName和UserEName不相等;解密后的UserID和UserEID不相等;客户端的Cookie少于必须的Cookie。然而在我测试的时候发现如果我将Cookie值改变成长度大于8的时候,程序就会报错,所以加上Try{}Catch{},当然此时用户肯定未登录。
下面是对字符串加密的方法,引用金色海洋--自然框架里面的:
public static string Encrypt(string sourceData) { //加密,固定密钥 //set key and initialization vector values //Byte[] key = new byte[] {0x21, 2, 0x88, 4, 5, 0x56, 7, 0x99}; //Byte[] iv = new byte[] {0x21, 2, 0x88, 4, 5, 0x56, 7, 0x99}; Byte[] key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; Byte[] iv = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; try { //convert data to byte array Byte[] sourceDataBytes = System.Text.ASCIIEncoding.UTF8.GetBytes(sourceData); //get target memory stream MemoryStream tempStream = new MemoryStream(); //get encryptor and encryption stream DESCryptoServiceProvider encryptor = new DESCryptoServiceProvider(); CryptoStream encryptionStream = new CryptoStream(tempStream, encryptor.CreateEncryptor(key, iv), CryptoStreamMode.Write); //encrypt data encryptionStream.Write(sourceDataBytes, 0, sourceDataBytes.Length); encryptionStream.FlushFinalBlock(); //put data into byte array Byte[] encryptedDataBytes = tempStream.GetBuffer(); //convert encrypted data into string return System.Convert.ToBase64String(encryptedDataBytes, 0, (int)tempStream.Length); } catch (Exception ex) { throw (ex); } }
由于篇幅的问题,这就不一一写出来了。可以下载源程序。
相关文章推荐
- 登录验证web服务引用时 "超时"报错处理...
- 对电话号码验证、掩码、加密适用匿名类处理
- 用户登录增加密码RSA加密验证功能
- 单点登录(十四)-----实战-----cas5.0.x登录mongodb验证方式常规的四种加密的思考和分析
- 用GUI写了一个登录验证(含时间加密)
- Codeigniter处理用户登录验证后URL跳转
- 关于使用HttpModule模块处理登录验证示例
- Asp.Net使用加密cookie代替session验证用户登录状态 源码分享
- 如何写出安全的API接口(参数加密+超时处理+私钥验证+Https)- 续(附demo)
- Joomla登录验证,密码加密方式
- [更新]一份包含: 采用RSA JWT(Json Web Token, RSA加密)的OAUTH2.0,HTTP BASIC,本地数据库验证,Windows域验证,单点登录的Spring Security配置文件
- 在Python中用Request库模拟登录(三):Discuz论坛(未加密,有验证码,有隐藏验证)
- 用户登录增加密码RSA加密验证功能
- 单点登录(十四)-----实战-----cas5.0.x登录mongodb验证方式常规的四种加密的思考和分析
- java/jsp实现SQLServer2012windows验证登录的相关处理操作
- jsf的初步使用(包括jsf框架的引入、用户登录、自定义表单验证、valueChangeEvent值变更事件处理做的级联下拉框)
- C# 在采集数据时的验证与登录处理
- 用不可逆算法MD5进行加密后,如何进行登录验证
- QuickCSharp框架开发(18)------加密用户名和密码数据与数据库读出的密码进行哈希比较(验证用户是否成功登录)
- 如何写出安全的API接口(参数加密+超时处理+私钥验证+Https)- 续(附demo)