保存登录信息的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

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

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形式就可以表示成

ee11cbb19052e40b07aac0ca060c23ee=EgkCFnUaFlI

5f4dcc3b5aa765d61d8327deb882cf99=vDwCZGvezDfudh91hRsiow

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

时间: 2024-08-24 22:23:27

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

[Android实例] 关于webview如何自动登录保存登录信息

2013-02-04 16:48 4291人阅读 评论(2) 收藏 举报 [转载请注明原作者和原文链接]这个是自己总结出来的经验,求版主推荐,求申精! 用户名密码登录验证后保存Session ? [java] view plaincopy // 你的URL HttpPost httppost = new HttpPost(Constants.ServerUrl.WEB_URL + url); try { List<NameValuePair> nameValuePairs = new Arra

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

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 在解决了asp.net core中访问memcached缓存的问题后,我们开始大踏步地向.net core进军--将更多站点向asp.net core迁移,在迁移涉及获取用户登录信息的站点时,我们遇到了一个问题--如何在asp.net core

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

php使用session来保存用户登录信息 使用session保存页面登录信息 1.数据库连接配置页面:connectvars.php <?php//数据库的位置define('DB_HOST', 'localhost');//用户名define('DB_USER', 'root');//口令define('DB_PASSWORD', '19900101');//数据库名define('DB_NAME','test') ;?> 2.登录页面:logIn.php <?php//插入连接数据

php使用cookie保存登录用户名的方法

php使用cookie保存登录用户名的方法 2015-01-26 11:03:13  www.hackbase.com  来源:互联网 提交表单页面复制代码代码如下:<?php$user = isset($_COOKIE['username'])?$_COOKIE['username']:'';?><form action="file.php" method="post">用户名:<input type="text"

使用cookie记录登录名,下次登录时能够记得上次的登录名,使用session记住登录信息并验证是否登录,防止利用url打开网站,并实现退出登录功能

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <

Mac下,使用sshpass让iterm2支持多ssh登录信息保存

Mac下,使用sshpass让iterm2支持多ssh登录信息保存 windows里有个Xshell非常的方便好使,因为它能保存你所有的ssh登录帐号信息.MAC下并没有xshell,有些也提供这样的功能,但效果都不好.iterm2是很好的终端,但却不能很好的支持多profiles,当要管理的机器较多时,就比较麻烦了.好在它有profiles设置,只是不能保存ssh登录帐号及密码,它还提供了加载profiles时执行外部命令的功能,因此,这里就可以使用sshpass来帮它执行. 安装iterm2

信息安全技术及应用 常规加密技术

一.密码技术与常规加密概述 1.1 密码系统 密码学:包含密码编码学和密码分析学两部分内容.前者是研究如何通过编码来保证信息的机密性,后者则研究如何破译密码. 一般加密模型 密码系统的主要功能:完成信息的加密变换和解密变换. 明文:加密变换前的原始信息. 加密算法:加密变换时使用的算法. 密文:经过加密变换后的信息. 解密算法:解密变换时使用的算法,是加密算法的逆过程.加密和解密算法是相关的. 密钥(Key):在加密和解密变换过程中引入一个相同或两个不同但相关的参数,该参数称为密钥.分为加密密钥

登录保存用户信息

做项目时,可能会将某些信息保存在session中,如登录等信息,这样方便在某些页面使用这些保存的信息. 要想保存这些信息,需要创建一个类,该类里面定义需要保存的变量等信息,当登录后就通过new一个该类来保存登录等信息,然后放在session中,需要用到这些信息时直接用例如EL表达式等取出来就OK了.例子如下: 1.保存用户信息的类 [java] view plain copy print? <span style="font-size:14px;"><span sty

会话管理(Cookie/Session技术)

什么是会话:用户打开浏览器,点击多个超链接,访问服务器的多个web资源,然后关闭浏览器,整个过程就称为一个会话: 会话过程需要解决的问题:每个用户在使用浏览器与服务器进行会话的过程中,都可能会产生一些数据,这些输入如何来进行保存?比如用户在购物网站浏览的商品记录,用户添加购物车的记录等等这些信息如何进行存储?在程序中会话跟踪是一件非常重要的事情,一个用户的所有请求操作都应该属于同一个会话,而另一个人的所有请求操作应该属于另一个人,二者不能混淆!当想到需要在保存数据时,我们首先肯定会想到使用域对象