应该怎么做一个登录功能?
版權(quán)是我的,轉(zhuǎn)載沒有通過我的同意的爬蟲都是傻逼.
假設(shè)有user表.里面有id,acount(賬戶,nvarchar(50)),pwd(密碼,nvarchar(50)).
最簡(jiǎn)單的實(shí)現(xiàn)
渣渣說做個(gè)登錄功能,那還不簡(jiǎn)單.
select * from user where ?acount=XX AND PWD =YY;
然而,某天,我們需要在登錄的時(shí)候更新最后登錄時(shí)間,也就是在user表里面加個(gè)lastLoginTime.
這時(shí)渣渣說
select id from user wher acount=XX AND PWD =YY;
update?user set XXXX where id=@id;
然后就他就被打了.實(shí)際上,可以合為一句:
update?user set XXXX where?acount=XX AND PWD =YY;
受影響行數(shù)大于0表示登錄成功.
密碼的加密
某一天,渣渣看到某某數(shù)據(jù)庫(kù)被下載了.想到自己的數(shù)據(jù)庫(kù)如果泄露了怎么辦,上面全是明文.
于是他就開始想加密這個(gè)事.
1MD5(同一個(gè)密碼,MD5還是一樣的,所以否決了)
2des(用于可逆密碼加密解密,然而有些安全系數(shù)要求高的密碼是不能被解密的,所以有適用范圍)
3隨機(jī)加鹽HASH.
第三種方案,要加在原來的表加多一個(gè)salt列.
每一次的登錄的話,
應(yīng)該是select *??from user wher acount=XX?
然后把里面的鹽加上輸入的密碼進(jìn)行hash然后與數(shù)據(jù)庫(kù)的加密后pwd進(jìn)行比較.比如string.equal(MD(pwd+salt),pwd)
true當(dāng)然就是說輸入正確啦.
其實(shí)加密的方案我舉的都只是最簡(jiǎn)單的例子.對(duì)于鹽的把握,大家開腦洞自己想吧.
(比如可以對(duì)原密碼進(jìn)行md5,然后對(duì)于md5的每一個(gè)偶數(shù)位字符插入鹽的一個(gè)字符,從而最后組成一個(gè)不明所以的字符串)
"無驗(yàn)證碼登錄"
我們?yōu)槭裁葱枰?yàn)證碼呢?是為了防止被密碼爆破.
那么是否可以無驗(yàn)證碼登錄呢?當(dāng)然可以.
遍地開花的開放平臺(tái)接口
比如支付寶,旺旺,qq,微博....
以qq為例.他的步驟無非就是,跳到一個(gè)指向自己應(yīng)用的騰訊鏈接.用戶在那上面授權(quán)給這個(gè)應(yīng)用.授權(quán)后返回token和openid給網(wǎng)站.
做過微信第三方服務(wù)器的人就知道,這個(gè)token是用來以授權(quán)者的名義做各種操作的,實(shí)際上,對(duì)于登錄,只要有這個(gè)openid,去數(shù)據(jù)庫(kù)檢索成功了,就應(yīng)該視為登錄有效.所以token其實(shí)沒啥用.
可信狀態(tài)下不需要驗(yàn)證碼
固定的上網(wǎng)行為
我們應(yīng)該怎么定義什么樣的狀態(tài)算作穩(wěn)定?比如,我單個(gè)用戶,連續(xù)10次的登錄有9次都是在同一個(gè)ip上登錄,那么這個(gè)ip的實(shí)際來源就應(yīng)該視為可信的狀態(tài).
固定的上網(wǎng)行為其實(shí)還有很多種,比如登錄的時(shí)間段眾數(shù),登錄的頻率,習(xí)慣使用的瀏覽器.只要你想的周全了,其實(shí)有很多用戶細(xì)節(jié)可以捕捉.
不頻繁的操作
我們相信這個(gè)世界的人大體都是美好的,所以你一看到我這個(gè)網(wǎng)站,要登錄的時(shí)候我就需要你輸入驗(yàn)證碼,但如果你連續(xù)數(shù)次密碼錯(cuò)誤,那我就要懷疑你的人品,給你下套.具體的可以看新浪微博.
場(chǎng)景的變換
不明公共wifi
我們知道http 下,明文post上去的明文被截取了就能分分鐘拿到信息.所以https就登場(chǎng)了.我post的密文就算給你看了,你也解密不了,耶~
然而這并沒有卵用.https證書根據(jù)不同的級(jí)別收不同的錢.于是12306自己做了個(gè)證書,哈哈.如果你們有魄力教導(dǎo)用戶安裝自己做的證書,那就走這條路吧....
移動(dòng)端(Android,iPhone)
這就是我最近遇到的一個(gè)比較蛋疼的問題.我們知道url有長(zhǎng)度限制,并且參數(shù)還得(utf-8)編碼.所以合適的做法應(yīng)該是可解密的json密文作為http請(qǐng)求報(bào)文的body傳上去.
然而.net環(huán)境的des默認(rèn)工作模式是cbc,所以其他客戶端也應(yīng)該用cbc進(jìn)行加密/解析.java的默認(rèn)實(shí)現(xiàn)不是cbc,而且它的偏移向量每次都隨機(jī).所以加密的結(jié)果和c#不一樣.
這里引用s站的說法,中文意思就是java的des是ecb而.NET的是cdc.工作模式不一樣.并且,我發(fā)現(xiàn)一些java 的des實(shí)現(xiàn)是用隨機(jī)向量的,所以變量不一致的話結(jié)果也會(huì)和.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個(gè)下午的時(shí)間研(抄)究(襲)出來的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的類,其余無區(qū)別
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)的我不知道,但是同事告訴我,轉(zhuǎn)成的base64除了大小寫有細(xì)微的差別外,沒有其他問題(他們請(qǐng)求我的web api接口有正確的響應(yīng)).
Android的,也許還能參考我的第一個(gè)參考鏈接.不過it does not work for me.
參考鏈接:
Android平臺(tái)和java平臺(tái) DES加密解密互通程序及其不能互通的原因 .
C# and Java DES Encryption value are not identical
?
版權(quán)是我的,轉(zhuǎn)載沒有通過我的同意的爬蟲都是傻逼.
?
轉(zhuǎn)載于:https://www.cnblogs.com/zeusro/p/4619873.html
總結(jié)
以上是生活随笔為你收集整理的应该怎么做一个登录功能?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NYOJ 311 完全背包
- 下一篇: shell中的小括号与大括号