開放平臺API接口安全性設計——微信支付爲例

API接口,相似http://mypay.com/refund/order_id=123&mch_id=123,這個請求我以商戶mch_id=123的身份給訂單號爲order_id=123退款,若是服務器不辯別請求發起者的身份直接作相應的操做,那是及其危險的。php

通常的,在PC端,咱們是經過加密的cookie來作會員的辨識和維持會話的;可是cookie是屬於瀏覽器的本地存儲功能。APP端不能用,因此咱們得經過token參數來辨識會員;而這個token該如何處理呢? 延伸開來,接口的安全性主要圍繞Token、Timestamp和Sign三個機制展開設計,保證接口的數據不會被篡改和重複調用。html

通常來講,在前端對數據作加密或者前面,是不現實的。先後端使用HTTP協議進行交互的時候,因爲HTTP報文爲明文,因此一般狀況下對於比較敏感的信息能夠經過在前端加密,而後在後端解密實現"混淆"的效果,避免在傳輸過程當中敏感信息的泄露(如,密碼,證件信息等)。不過前端加密只能保證傳輸過程當中信息是‘混淆’過的,對於高手來講,打個debugger,照樣能夠獲取到數據,並不安全,所謂的前端加密只是稍微增長了攻擊者的成本,並不能保證真正的安全。即便你說在前端作了RSA公鑰加密,也頗有可能被高手獲取到公鑰,並使用該公鑰加密數據後發給服務端,因此務必認爲前端的數據是不可靠的,服務端要加以辯別。敏感信息建議上https。前端

因此通常建議上https,敏感信息md5混淆,前端不傳輸金額字段,而是傳遞商品id,後端取商品id對應的金額,將金額等參數加簽名發送到支付系統。金額能夠是明文的。 java

加密

一. Token

token受權機制:用戶使用用戶名密碼登陸後,後臺給客戶端返回一個token(一般是UUID),並將Token-UserId鍵值對存儲在redis中,之後客戶端每次請求帶上token,服務端獲取到對應的UserId進行操做。若是Token不存在,說明請求無效。 弊端:token能夠被抓包獲取,沒法預防MITM中間人攻擊redis

二. Timestamp

用戶每次請求都帶上當前時間的時間戳timestamp,服務器收到請求後對比時間差,超過必定時長(如5分鐘),則認爲請求失效。時間戳超時機制是防護DOS攻擊的有效手段。算法

三. Sign和RSA算法

將token,timestamp等其餘參數以字典序排序,再加上一個客戶端私密的惟一id(這種通常作在服務端,前端沒法安全保存這個id)或使用私鑰簽名,將前面的字符串作MD5等加密,做爲sign參數傳遞給服務端。後端

四. 公鑰加密,私鑰簽名

地球上最重要的加密算法:非對稱加密的RSA算法。公鑰加密的數據,能夠用私鑰解密;私鑰簽名(加密)的數據,能夠用公鑰驗籤。api

1977年,三位數學家Rivest、Shamir 和 Adleman 設計了一種算法,能夠實現非對稱加密。這種算法用他們三我的的名字命名,叫RSA算法。瀏覽器

RSA原理是對極大整數作因數分解,如下摘自維基百科。 安全

公鑰加密
解密和驗籤

五. 微信支付的簽名方式

暫時比較忙沒時間,將於7月29日晚更新。 來更新啦。 微信支付安全規範,能夠查看官方文檔pay.weixin.qq.com/wiki/doc/ap… 第1點中,其簽名算法最重要的一步,是在最後拼接了商戶私密的API密鑰,而後經過md5生成簽名,這時即便金額是明文也是安全的,若是有人獲取並修改了金額,可是簽名字段他是沒法僞造的,由於他沒法知道商戶的API密鑰。固然,除了微信支付的拼接API生成簽名的方法,咱們也能夠經過java自帶的security包進行私鑰簽名。其中nonce隨機字符串,微信支付應該作了校驗,能夠防止重放攻擊,保證一次請求有效,若是nonce在微信支付那邊已經存在,說明該請求已執行過,拒絕執行該請求。

API密鑰

參考資料

  1. 阮一峯老師的博客-RSA算法原理:www.ruanyifeng.com/blog/2013/0…
  2. 維基百科:zh.wikipedia.org/wiki/RSA%E5…
相關文章
相關標籤/搜索