時間:2015-02-26 做者:Abyssly 來源:Abyssly Blogphp
最近因爲工做須要,接觸了微信公衆號的開發。業務上要求綁定微信用戶和系統用戶,以便用戶在一次綁定後可以經過系統用戶的身份去使用一些功能。我關注的招行信用卡公衆號實現了這個功能,因此估計仍是可行的,在網上搜索了一下,發現這個問題沒什麼好的答案,不少都說取不到微信用戶名實現不了,甚至有說實現了這個功能的應該是與微信有內部合做的。html
搜索無果,遂本身動手實驗,後發現其實徹底能夠的,看來實踐纔是檢驗真理的惟一標準,方案上也很簡單,我分幾點來講。數據庫
用OpenID綁定便可瀏覽器
微信接口中雖然沒給用戶的微信帳號,但給了用戶的OpenID,這個OpenID對一個公衆號是惟一的,測試也證實不會改變,也就是說同一個微信號和同一個公衆號交互,咱們獲得的OpenID是不會變的,所以,能夠用OpenID做爲微信用戶的身份標識。安全
如何綁定服務器
俗話說,沒吃過豬肉還沒見過豬跑。看招行信用卡公衆號是如何作的,在微信裏面給用戶一個驗證連接,用戶點擊連接,微信會用內嵌的瀏覽器打開這個連接,而後就是通常的網頁登陸驗證界面,咱們經過HTTP(S)獲取用戶輸入的系統用戶名與密碼,驗證經過後完成綁定。 具體如何生成連接和如何傳遞OpenID下面詳述。微信
如何生成綁定連接cookie
綁定涉及到用戶的身份甚至利益,因此須要注意安全性。咱們須要綁定的是OpenID和系統用戶,系統用戶名是用戶直接在連接頁面輸入後經過HTTP(S)傳給咱們的,這沒有問題。OpenID對用戶來講透明,用戶不會傳給咱們,咱們也只有在用戶在微信中向公衆號發消息時纔可得到OpenID,因此很明顯,OpenID須要包含在生成的連接中,至於需不須要對OpenID做加密就看你本身了,我以爲這不重要,更爲重要的是要在連接中帶上簽名和加上時間戳。由於咱們須要確認這個連接是由咱們服務端生成的,用戶本身或者其餘人不可以僞造出這個連接,加上時間戳是爲了給這個連接一個過時時間,若是不限制過時時間,假設用戶綁定後這個連接經過某種方式被別人知道,那麼這我的就能夠把本身的帳號與用戶的微信號綁定。因此我採起的方法是用OpenID、過時時間再加上一個密鑰生成簽名,生成簽名的方法和微信服務器接口驗證時的簽名方法相似(密鑰最好另選一個只有本身知道的)。session
如何傳遞OpenID測試
有了綁定連接,用戶點了綁定連接,但這只是第一步,第二步咱們須要在用戶在連接頁面提交登陸請求後進行驗證,OpenID怎麼傳到第二步中呢?有人說了,這還不簡單,在登陸表單中加一個隱藏域放用戶的OpenID一塊兒提交給驗證的Handler不就OK了,那我只能說很遺憾,你前面所作的安全工做都白費了,一旦A用戶的OpenID泄漏,B用戶就能夠把本身的帳號與A用戶的微信號綁定了。因此永遠不要相信客戶端提交的東西。個人方法是當用戶點擊生成連接後,在連接頁載入時,將OpenID存到session中,由於這個session是無法僞造的(cookie被盜除外),因此只有點擊這個連接的用戶的session中才會有連接中包含的OpenID。
關於微信服務器簽名多說一句
你們都知道微信公衆號消息接口驗證時微信會向咱們服務器發一個GET請求,在其中帶上只有咱們和微信服務器知道的簽名,咱們在請求處理Handler中會驗證這個簽名,這點你們無異議;消息接口驗證經過後,微信就會把用戶發的消息以POST的方式發給咱們,不少人可能會在這裏忽視對簽名的檢查,從而給惡意者僞造用戶請求的機會。在微信以POST方式傳遞用戶的消息時,仍然會將簽名信息附在URL參數中,咱們在處理每個POST請求時,第一步仍是得像處理消息接口驗證時同樣,去對URL參數中的簽名做驗證,只有簽名驗證經過後纔可去取POST的信息。
綁定流程的詳細描述
我在上面說了基本方法,但不夠詳細,致使一些新手朋友仍是不清楚具體如何操做,因此我在此嘗試更加詳細地描述整個過程的每一步:
1. 用戶OpenID:由於你須要在綁定頁面中取到是哪一個微信用戶想要綁定系統用戶。 2. 時間戳timestamp:這是爲了防止連接泄漏出去被惡意利用,具體來講就是一個你指定的過時時間,超過這個時間這個連接就失效了,用戶只能再次獲取。 3. 簽名signature:這是爲了保證此驗證連接只有你纔可能生成,用戶及第三方均沒法僞造。
1. 將token、OpenID、timestamp三個參數進行字典序排序。 2. 將三個參數字符串拼接成一個字符串進行sha1加密,獲得連接的signature參數。
關於微信公衆號用戶帳號綁定就是這麼多,其實很容易實現,我在這裏把個人方法和你們分享一下,老鳥能夠忽略,主要是但願對新手有一些幫助。歡迎探討,敬請輕拍。