zoukankan      html  css  js  c++  java
  • 保存登录信息的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形式就可以表示成

    ee11cbb19052e40b07aac0ca060c23ee=EgkCFnUaFlI

    5f4dcc3b5aa765d61d8327deb882cf99=vDwCZGvezDfudh91hRsiow

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

  • 相关阅读:
    initwithcoder和 initwithframe 区别?
    iOS图形处理和性能
    iOS图形处理和性能
    Objc的底层并发API
    Objc的底层并发API
    位运算
    位运算
    网页开发的6种在线调试环境
    网页开发的6种在线调试环境
    Python基本语法_函数属性 & 参数类型 & 偏函数的应用
  • 原文地址:https://www.cnblogs.com/VectorZhang/p/5425283.html
Copyright © 2011-2022 走看看