作為一家大資料公司,glow不僅重視使用者的資料,更加注重資料的安全性。
本文將從使用者註冊流程出發,逐步介紹我們在提高資料安全性方面採用的一些策略方法,供讀者參考。下面將從android
和服務端
兩部分來進行講解。
這對於任何一家企業而言都是非常可怕的。
下面先對https的基本工作原理進行下介紹,以便後文的講解。
首先,客戶端去請求服務端的數字證書
,這個證書包含了乙個公鑰。該證書購買後儲存於我們自己伺服器上。
當服務端收到客戶端請求後,會把這個數字證書回傳給客戶端,由於是公鑰,所以不害怕被竊取。
客戶端收到數字證書後,先去驗證
證書的真實性。如果驗證通過,就會從裡面取出乙個公鑰
。
客戶端本地生成乙個隨機數
,作為未來的會話私鑰
,利用前面的公鑰進行加密
。
客戶端把加密後會話私鑰
回傳給服務端,在這個過程中,即使加密後的會話私鑰
被竊取也不用擔心,因為中間人並沒有解密私鑰
,所以讀不出裡面的會話私鑰
。
服務端接收到加密會話私鑰
後,利用從ca購買證書時獲得的解密私鑰
進行解密讀出真實會話私鑰
。至此,客戶端與服務端同時擁有了乙個只有它們二者知道的會話私鑰
,非對稱加密連線建立完成。
一旦客戶端和服務端連線建立起來後,未來的資料通訊都利用這個會話私鑰
進行對稱加密傳輸資料。
採用了https後,我們所有網路傳輸的資料都由明文變成了密文,即使中間有人能夠監聽到資料報,也不能輕易獲取user的帳戶密碼資訊。
聽起來,安全性問題基本解決了。
然而實際上,在步驟3使用者需要去驗證數字證書時,如果這個驗證過程被欺騙了呢?
試想這樣一種場景,如果在最開始,攻擊者就攔截掉客戶端與服務端的通訊。當客戶端在請求證書時,攻擊者回傳乙個他自己的假證書
,而且攻擊者已經通過其他手段欺騙使用者在手機上信任
了這個假證書
,那麼當客戶端接收到證書並去驗證時,是可以通過的
。這也就意味著,一旦客戶端遭受這樣的攻擊,未來客戶端都會與乙個虛假的中間人
通訊,而且中間人也可以拿著客戶端傳來的資訊去與我們的服務端通訊,而這個過程客戶端和我們服務端完全不知道中間人的存在
,這是很大的安全隱患。
為了防止客戶端被虛假證書欺騙,可以採取的方式是把我們自己的公鑰直接繫結給客戶端,當客戶端收到證書後,與提前繫結好的公鑰進行驗證,從而防止虛假證書
的入侵。
在android端,我們利用okhttp3
提供的certificatepinner
實現公鑰繫結
.build();至此,我們可以利用更為安全的https協議來傳輸使用者名稱和密碼,我們繼續來看上面的註冊流程。
回到註冊流程。當服務端拿到使用者名稱密碼後,會去建立乙個新的user
,同時我們會基於使用者相關資訊生成乙個token
並回傳給客戶端。客戶端在接收到token
後需要在本地進行儲存。另外,由於每個http請求都是無狀態的,因此未來客戶端如果想把user
資訊傳遞給服務端時,就必須通過token
來傳遞,才能識別出某個請求的**。
那麼,我們應該如何在android和服務端的**裡具體實現token的傳遞
、解析
及有效性驗證機制
呢?
1. 首先在android端,為了把token
資訊存入到所有請求的http header
裡,我們採用了okhttp3
提供的interceptor介面
來。
.build();2. 然後在服務端,我們需要解析
客戶端傳遞過來的token資訊並進行校驗
。這裡可以建立乙個python
的decorator
方法:
def
mobile_request
(func):
@functools.wraps(func)
def(*args, **kwargs):
kwargs = kwargs if kwargs or {}
if request.headers.get('authorization'):
encrypted_token = request.headers.get('authorization')
isvalid, user_info = check_token(encrypted_token) //解析並驗證token有效性
ifnot isvalid:
abort(498) //token無效,返回498狀態碼
user = get_user(user_info)
ifnot user:
abort(403) //找不到user,返回403狀態碼
kwargs['user_info'] = user_info //成功解析出user_info
return func(**kwargs)
@mobile_request // 使用decorator包裝方法
defget_user
(**kwargs):
user_info = kwargs['user_info'] // 取出decorator中封裝好的user_info
return db.get_user(user_info) // 利用user_info進行邏輯處理
3. 最後,請求結果返回到客戶端,如果通過監測狀態碼發現返回結果是與token相關的error/異常
,則表示token失效
,此時我們讓使用者強制重新登入,生成新token。這一步仍然可以在上面的interceptor
裡進行。
.build();至此,我們完成了android端和服務端的token傳遞、解析和失效處理。
在完善了token的管理機制後,我們未來的http請求中只要帶上這個token,就可以暢通無阻地去服務端做與自身user相關的各種操作了。
那麼,既然token像家裡門禁卡一樣,只要擁有就能進入我們服務端並獲取這個特定user的所有資料。那也就意味著,一旦攻擊者竊取了某個user的token,那在token失效前,攻擊者隨時可以利用這個token獲取這個user的一切資訊。
遇到token被盜,該怎麼辦呢?
針對token被盜這種威脅,我們可以縮短token的過期時間的方法。這樣即使乙個token洩漏了,在一段時間後,這個token也會自動失效。當然這也做會需要使用者頻繁登入獲取新token;而且失效前的這段時間內,攻擊者仍然是可以直接連上服務端隨意獲取資料的。
這種方法也是oauth推薦的一種方法,其原理是在客戶端和服務端統一好某種加密方法和乙個金鑰,這個金鑰同時儲存在客戶端和服務端。每次客戶端準備發起乙個請求時,利用這種加密演算法和金鑰,針對該請求的api和引數進行計算得到乙個數,稱之為這個request的簽名
,然後我們把這個簽名
放入到request中。當服務端接收到request後,就可以利用相同的加密演算法和金鑰來驗證其中簽名的真實性。
}).build();通過對每乙個request簽名,可以確保服務端接收到的所有request都來自我們自己的客戶端。即使有人得到了token想偽造request,他也不知道如何計算request簽名,從而減小了token被盜的危害。
當然,每種安全方法都有漏洞,request簽名的方法意味著我們必須在客戶端儲存好加密演算法和金鑰,可以通過**混淆、金鑰儲存到.so檔案等方法來提高破解難度,這裡就不再細述了。
上文中,從註冊流程開始,介紹了我們在資料安全性方面採取的一些策略和相關實現**,希望能對讀者有幫助。
最後,筆者認為沒有完美的安全策略來確保萬無一失,不過我們所做的每一步都能夠加大被攻擊的難度。
談談多執行緒程式設計(一) 安全性策略
在多執行緒程式設計中,安全是我們考慮的最重要的因素。通常程式設計師都會使用鎖來滿足安全要求,但是只用鎖並不能寫出良好的多執行緒 因此我們有必要更深入一點,對執行緒安全策略進行更加全面的了解。首先談談影響執行緒安全的因素 有三個因素影響到了多執行緒下的安全性 原子性 可見性和指令順序 請看下面的 不安...
利用大資料實踐安全性
安全性的問題往往是在某款應用程式飛速發展成熟之後,才開始對其進行反思。大資料也不例外。隨著近來幾乎每個星期都有新的安全漏洞和黑客高調的攻擊事件頻頻登上 的頭版新聞,it安全問題已然不再僅僅侷限於只是it領導圈內飯桌上的技術討論談話話題了。這種討論很容易讓人們陷入恐懼甚至厭惡,而長期關注我的專欄文章的...
Ubuntu的安全性
現在ubuntu 的安裝源還不是很多,以後大量的非官方源出現會不會出現安全問題呢?下面是幾個德國源 據說軟體比官方源新。首先,在終端下執行下面的命令開啟源代表,sudo gedit etc apt sources.list 然後把這兩行加入 再拿把安全金鑰 完了以後,就sudo apt get up...