zoukankan      html  css  js  c++  java
  • 应该怎么做一个登录功能?

    版权是我的,转载没有通过我的同意的爬虫都是傻逼.

    假设有user表.里面有id,acount(账户,nvarchar(50)),pwd(密码,nvarchar(50)).

    最简单的实现

    渣渣说做个登录功能,那还不简单.

    select * from user where  acount=XX AND PWD =YY;

    然而,某天,我们需要在登录的时候更新最后登录时间,也就是在user表里面加个lastLoginTime.

    这时渣渣说

    select id from user wher acount=XX AND PWD =YY;

    update user set XXXX where id=@id;

    然后就他就被打了.实际上,可以合为一句:

    update user set XXXX where acount=XX AND PWD =YY;

    受影响行数大于0表示登录成功.

    密码的加密

    某一天,渣渣看到某某数据库被下载了.想到自己的数据库如果泄露了怎么办,上面全是明文.

    于是他就开始想加密这个事.

    1MD5(同一个密码,MD5还是一样的,所以否决了)

    2des(用于可逆密码加密解密,然而有些安全系数要求高的密码是不能被解密的,所以有适用范围)

    3随机加盐HASH.

    第三种方案,要加在原来的表加多一个salt列.

    每一次的登录的话,

    应该是select *  from user wher acount=XX 

    然后把里面的盐加上输入的密码进行hash然后与数据库的加密后pwd进行比较.比如string.equal(MD(pwd+salt),pwd)

    true当然就是说输入正确啦.

    其实加密的方案我举的都只是最简单的例子.对于盐的把握,大家开脑洞自己想吧.

    (比如可以对原密码进行md5,然后对于md5的每一个偶数位字符插入盐的一个字符,从而最后组成一个不明所以的字符串)

    "无验证码登录"

    我们为什么需要验证码呢?是为了防止被密码爆破.

    那么是否可以无验证码登录呢?当然可以.

    遍地开花的开放平台接口

    比如支付宝,旺旺,qq,微博....

    以qq为例.他的步骤无非就是,跳到一个指向自己应用的腾讯链接.用户在那上面授权给这个应用.授权后返回token和openid给网站.

    做过微信第三方服务器的人就知道,这个token是用来以授权者的名义做各种操作的,实际上,对于登录,只要有这个openid,去数据库检索成功了,就应该视为登录有效.所以token其实没啥用.

    可信状态下不需要验证码

    固定的上网行为

    我们应该怎么定义什么样的状态算作稳定?比如,我单个用户,连续10次的登录有9次都是在同一个ip上登录,那么这个ip的实际来源就应该视为可信的状态.

    固定的上网行为其实还有很多种,比如登录的时间段众数,登录的频率,习惯使用的浏览器.只要你想的周全了,其实有很多用户细节可以捕捉.

    不频繁的操作

    我们相信这个世界的人大体都是美好的,所以你一看到我这个网站,要登录的时候我就需要你输入验证码,但如果你连续数次密码错误,那我就要怀疑你的人品,给你下套.具体的可以看新浪微博.

    场景的变换

    不明公共wifi

    我们知道http 下,明文post上去的明文被截取了就能分分钟拿到信息.所以https就登场了.我post的密文就算给你看了,你也解密不了,耶~

    然而这并没有卵用.https证书根据不同的级别收不同的钱.于是12306自己做了个证书,哈哈.如果你们有魄力教导用户安装自己做的证书,那就走这条路吧....

    移动端(Android,iPhone)

    这就是我最近遇到的一个比较蛋疼的问题.我们知道url有长度限制,并且参数还得(utf-8)编码.所以合适的做法应该是可解密的json密文作为http请求报文的body传上去.

    然而.net环境的des默认工作模式是cbc,所以其他客户端也应该用cbc进行加密/解析.java的默认实现不是cbc,而且它的偏移向量每次都随机.所以加密的结果和c#不一样.

    这里引用s站的说法,中文意思就是java的des是ecb而.NET的是cdc.工作模式不一样.并且,我发现一些java 的des实现是用随机向量的,所以变量不一致的话结果也会和.net的不一样.

    SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES, DES-EDE and Blowfish ciphers. (JCA Doc)

    In .Net, The default operation mode for the symmetric algorithm is CipherMode.CBC and default padding is PaddingMode.PKCS7. (msdn..SymmetricAlgorithm)

            /// <summary>
            ///  DES加密字符串
            /// </summary>
            /// <param name="encryptString">待加密的字符串</param>
            /// <param name="key"></param>
            /// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
            public static string DESEncrypt(this string encryptString, string key)
            {
                try
                {
                    if (key.Length < 8)
                        throw new ArgumentException("密钥和向量必须为8位,否则加密解密都不成功", "key");
                    byte[] rgbKey = Encoding.UTF8.GetBytes(key.Substring(0, 8));
                    byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
                    using (var dCSP = new DESCryptoServiceProvider())
                    {
                        using (MemoryStream mStream = new MemoryStream())
                        {
                            using (var cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbKey), CryptoStreamMode.Write))
                            {
                                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                                cStream.FlushFinalBlock();
                                cStream.Close();
                                return Convert.ToBase64String(mStream.ToArray());
                            }
                        }
                    }
                }
                catch
                {
                    return encryptString;
                }
            }
    

      这下面是哥用了2015年7月3日用了0.7个下午的时间研(抄)究(袭)出来的java加密代码

    import java.util.HashMap;
    import java.util.Map;
    
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.KeyGenerator;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.SecretKeySpec;
    
    import java.security.InvalidAlgorithmParameterException;
    import java.security.Key;
    import java.security.Security;
    
    import javax.crypto.spec.DESKeySpec;
    import javax.crypto.spec.IvParameterSpec;
    
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.security.spec.KeySpec;
    
    import net.sf.json.JSONArray;
    import net.sf.json.JSONObject;
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    
        public static void main(String[] args) throws Exception {
      
               
               Map map = new HashMap();  
               map.put( "Msg", "哦" );  
               map.put( "Url", "oooo");                       
               JSONObject jsonObject = JSONObject.fromObject( map );  
               String shit=jsonObject.toString();
               System.out.println(shit);  
                  System.out.println(encrypt(shit,"UTF8"));
                   }
        public static String encrypt(String message,String encoding,String myKey) throws Exception {  
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");  
             DESKeySpec desKeySpec = new DESKeySpec(myKey.getBytes(encoding));  
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
            SecretKey secretKey = keyFactory.generateSecret(desKeySpec);  
            IvParameterSpec iv = new IvParameterSpec(myKey.getBytes(encoding));  
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);  
            byte[] buf = cipher.doFinal(message.getBytes(encoding));        
            sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
            String a =   encoder.encode(buf);
             
          return a;  
        }  

    这是哥移植到安卓的代码,只是最后的base64用了Android的类,其余无区别

    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESKeySpec;
    import javax.crypto.spec.IvParameterSpec;
    public static String encrypt(String key, String message, String encoding) throws Exception {
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes(encoding));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        IvParameterSpec iv = new IvParameterSpec(key.getBytes(encoding));
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
        byte[] buf = cipher.doFinal(message.getBytes(encoding));
        return android.util.Base64.encodeToString(buf, android.util.Base64.DEFAULT);
    }

      

    ios(object c)的我不知道,但是同事告诉我,转成的base64除了大小写有细微的差别外,没有其他问题(他们请求我的web api接口有正确的响应).

    Android的,也许还能参考我的第一个参考链接.不过it does not work for me.

    参考链接:

    Android平台和java平台 DES加密解密互通程序及其不能互通的原因 .

    C# and Java DES Encryption value are not identical

    版权是我的,转载没有通过我的同意的爬虫都是傻逼.

  • 相关阅读:
    poj 3436 ACM Computer Factory 夜
    poj 1182 食物链 夜
    poj 2299 UltraQuickSort 夜
    E. Printer 夜
    poj 3083 Children of the Candy Corn 夜
    sdut 2500 0\'s 夜
    1776. Anniversary Firework sdut 2507 焰火表演 夜
    删除上传文件中可能包含的空行
    ALV的fieldcat属性
    ALV显示红绿灯(FM&nbsp;ALV&nbsp;和&nbsp;OO&nbsp;ALV两…
  • 原文地址:https://www.cnblogs.com/zeusro/p/4619873.html
Copyright © 2011-2022 走看看