app 登錄淺析
1.登錄方式
(1)登錄方式
一般有以下幾種登錄方式
傳統的賬號密碼登錄,如下面的知乎賬號/密碼 登錄,賬號可以是郵箱,手機號或者賬戶名
手機驗證碼登錄,如下面的今日頭條手機驗證碼登錄
第三方登錄,如下面的額知乎日報,上面的今日頭條也一樣
還有一些新型的登錄方式,比如圖案鎖,指紋,語音驗證,虹膜掃描等等,這些都是在client進行驗證,或者是一種變種的賬號密碼形式,在這里不作討論。`為表述方便,分別使用 賬密 , 驗證碼 和 第三方 來表述上面三種登錄方式。
(2)登錄方式的大概流程
賬密:用戶在client輸入賬號密碼,發送到server端,server端進行database驗證,如果驗證通過則該用戶認證成功,否則認證失敗
驗證碼:用戶輸入手機號,并且點擊獲取驗證碼,server產生隨機驗證碼并打上過期時間,通過SMS傳輸給用戶,client輸入該驗證碼,傳到server進行判斷
第三方:第三方相對復雜一點,client需要先到第三方網站或者APP進行授權,授權后跳轉到server,server通過code碼獲取到相應的access_token,然后通過access_token獲得這個用戶在這個第三方的基本信息。
(3)登錄方式的優缺點以及適用場景
賬密:安全性相對較高,需要用戶輸入保護信息。使用場景較廣,一般的應用都能夠適用。
驗證碼:優點是便捷,缺點是安全系數相對較低,手機丟失即賬號丟失,一般用在驗證不是非常嚴密的應用,比如新聞資訊,地圖這種獲取咨詢的app或者一些即用即關的一些應用,比如滴滴,貨拉拉這種app,(注:內部支付有另外的驗證)。
第三方:優點同樣是便捷,比手機號還要編輯,都不需要輸入驗證碼。安全性需要依托第三方的可信度。不過現在微信,微博等第三方的登錄還是相對比較安全的。使用范圍相對較廣。便捷性方面不定,需要依托第三方的便捷性,比如微信就是需要安裝微信的app,而有些第三方登錄會跳轉到該第三方的登錄網站中,使用賬號密碼登錄。所以安全性方面需要看第三方了,像微信這樣的直接點擊確定登錄肯定沒有輸入第三方賬號密碼安全。綜合來講 第三方 登錄安全性不差,便捷性較高,另外不用注冊新的賬號密碼,在現在的登錄方式中非常普遍。
2.認證(Authentication)
首先普及兩個知識點:
a. 認證(Authentication)和授權(Authorization) 。借用別人的一個例子,你要登陸論壇,輸入用戶名張三,密碼1234,密碼正確,證明你張三確實是張三,這就是 authentication;再一check用戶張三是個版主,所以有權限加精刪別人帖,這就是 authorization。
b. token :token就是令牌的意思。為什么client中使用token代替cookie/session呢?token去掉了服務器端的狀態保持,擴展性更好,不需要在服務器進行存儲,只需要驗證就好。
(1)賬密認證
b1b31c5f-d4ad-44b4-ae2a-3092b2e5474a.png
Client指的是移動終端,Application指的是應用服務器。
賬密的認證很簡單,數據庫驗證下就行。
注意:密碼一般都會使用MD5進行hash下
(2)驗證碼認證
比賬號密碼多了步產生驗證碼的過程,并且匹配一般在緩存數據庫(如memcache或者redis)中進行,驗證是需要驗證過期時間。
(3)第三方認證
對于說使用友盟和shareSDK的同學,這篇文章不是講怎么做,而是表述一些我在APP登錄方面的一些見解,以及原理剖析。
為了描述清楚,使用微信作為代表(事先需要到各個迪桑放網站注冊自己的server Application)
步驟如下:
1.client點擊微信圖標登錄,帶上Application ID和scope,這些都是在你注冊Application的時候可以看到的
2.微信SDK會調用本地接口,打開微信的授權頁,如下:
3.點擊確定登錄,微信server驗證用戶,然后會redirect to 你的Application server,帶上code碼
4.code碼的有效期很短,需要立即使用code碼用API從微信server換取 access_token 等驗證數據
5.application獲取到token后就能將這些數據存儲到數據庫,(數據庫具體格式后面會有介紹)。并且通過 access_token 從微信server拿到用戶的一些基本信息,比如頭像,昵稱等等。
6.有些應用不允許單獨社交賬號存在,必須綁定手機號碼/密碼,因此對于不同的業務,不同的場景各自去做。這其實也是一大塊,手機號碼的綁定,解綁,注冊,第三方賬號的綁定解綁,綁定到另外的手機號,密碼找回,是否用手機號為主賬號,等等等等一系列的業務邏輯,各個公司各個產品因為安全性能要求和設計不同,表現形式也是多種多樣。在這里不做詳細的探討了,有興趣的同學可以自己去梳理梳理。
7.application server產生自己的 access_token ,返回給client,client進行用戶數據的訪問和API的調用。
關于微信的第三方登錄流程具體的可以去 微信開放平臺 中的->資源中心->移動應用->微信登錄功能。其他的平臺都差不多。
Client始終沒有拿到第三方的token,是因為client獲取第三方數據完全可以通過server中轉,這樣就避免將token暴露給Client,這樣第三方中用戶的數據也會更加安全
3.授權(Authorization)
對于不同的登錄方式會有不同的認證過程,但是授權就需要進行統一管理。
授權的關鍵點在于怎么產生一個好的access_token讓client進行數據訪問。oAuth2是一個很好的解決方案,JWT(JSON Web Token)是目前比較流行也比較安全的一種token產生和驗證機制。
當然也可以自己產生token,一般使用"時間戳+UserGuid+椒鹽噪聲"然后非對稱加密,傳輸給Client。JWT是一種更加規范,更加安全的Token的生成和校驗方式。
授權過程:
(1)認證成功后,得到或者生成 UserGui d(用戶的唯一id碼,同一個賬戶的不同登錄方式擁有同一個 UserGuid ),然后通過JWT生成token,token中包含 UserGuid ,token過期時間等等。
(2)將JWT token傳送給client,client收到后保存下來。之后在向服務器請求數據時帶在Header上
(3)服務器收到client的請求,然后使用中間件進行JWT拆分,得到其中的token過期時間, UserId 以及其他一些Claims。根據其中的Claim進行身份校驗,這里不同的server有不同的操作。
注意:1.JWT token是明文傳輸的,可以通過 base64url_decode 獲得其中的Claims信息,因此不要將敏感信息放進去
2.JWT的安全:因為JWT的第三部分是通過HS256加密的,所以client不能夠通過Claims進行仿造token,這樣會導致在server校驗不通過。但是如果整個token被盜取了就沒有辦法了,畢竟這個tokn是所有請求權限的令牌。當然也可以通過在token中添加設備碼等信息進一步加強其安全性。
3.token過期刷新問題:如果server檢查到client的token過期,就會返回401錯誤。而一般的token設置有效期不長,總不能每次過期就重新登錄吧。有兩個解決方案。一是在在有效時間,比如在時間到達有效時間的3/4時,就開始向客戶端推送新的token,最極端的做法是每次請求都換token,這樣安全性高,但是太費server資源,并且在高并發情況下會有舊的請求被否決的情況。還有一種方案,就是在過期時間外再設定一個刷新時間期限的Claim,這個時間設定長一些,跟OAuth2中的 refresh_token 相似。當檢測到token過期時,查看刷新時間過期沒有,如果沒有過期,則重新生成JWT token返回給client。
4.server端數據庫設計
用戶登錄模塊在數據庫模塊也需要好好設計,不能因為每添加一種第三方認證就修改數據庫表。
(1)用戶基本信息表User
UserID | avatar | name | ... |
---|---|---|---|
2 | url1 | name1 | - |
1 | url2 | name2 | - |
3 | url3 | name3 | - |
用戶基本信息表包含一些用戶基本信息,主鍵是用戶的 UserGuid ,是唯一的。
(2)用戶驗證表User_auths
primary | UserID | identity_type | identify | credential | isFirstParty |
---|---|---|---|---|---|
1 | 2 | 12345@gmial.com | MD5MD5MD5 | True | |
2 | 2 | account | accountName | accountPwMD5 | True |
3 | 1 | phone | 12345678909 | pwMD5 | True |
4 | 2 | wechatID | access_token & refresh_token | False | |
5 | 3 | weiboID | access_token & refresh_token | False |
用戶驗證表,包含用戶的各種登錄方式,對列名解釋: primaryKey :主鍵,唯一。 UserGuid :用戶唯一標識,在表中不唯一。 identity_type :登錄方式。 identify :該方式的賬戶名或ID。 isFirstParty :是否是第一方登錄。 credential :對于第一方是密碼,對于第三方是 access_token 和 refresh_token 。
很多現在的APP第三方登錄成功獲得用戶基本資料后便丟棄第三方的 access_token 和 refresh_token ,其實如果為了真正的安全,還是需要保存下來,每次自動登錄后通過第三方 access_token 和 refresh_token 來更新用戶信息以及驗證用戶是否是真實身份。
UserGuid 不唯一,可能有多個賬號對應同一個 UserGuid (第三方綁定到電話賬號等等)。使用 isFirstParty 來標注是否是第一方,對于有些應用email/phone/accout的密碼是同一個,修改的話就需要同時修改,需要通過標志位來定位這些第一方賬號。
來自:http://www.jianshu.com/p/c95c4741d725