我的公眾號開發(第五步)python實現公眾號消息加密

我的公眾號開發(第五步)python實現公眾號消息加密

作者:JiawuZhang

出品:JiawuLab(ID:jiawulab)

實驗記錄系列是JiawuLab原創欄目,通過真實項目的操作,記錄整個實驗過程。

旨在通過一步步過程,零基礎的朋友都能直接上手。

大家好,我是JiawuZhang,本次實驗記錄的項目是——微信公眾號開發。

我的公眾號開發的第五篇文章,如果您沒看過前四篇文章,這裡是傳送門:

我的公眾號開發(第一步)簡單功能實現

我的公眾號開發(第二步)智能AI對接

我的公眾號開發(第三步)數據庫實現關鍵字回覆

我的公眾號開發(第四步)圖文消息回覆

希望您多多關注。

上期回顧

我們首先新增圖文消息回覆,用一種更美觀的方式來進行消息回覆

並且讓數據庫更輕鬆,可承載更多的併發處理

最後也擁有了日誌功能。

現在已經擁有了相對完整的功能,只需要日後根據運營情況,進行完善相關功能就行。

不過為了安全,我們還得多做一步,就是消息加密,本期我們就來實現它。

本期知識點

1、消息加密

2、後續工作

吐槽兩句

官方對於消息加密的資料太亂了,本來我認為公眾號的資料就能解決,想不到還要跑到開放平臺找資料

再就是示例代碼中的坑有點多,尤其是對python3而言,在處理過程中,經常要調試

Web.py的一個bug太坑了,也是針對python3的,就是在POST方法中,使用web.input()方法會出錯

一直報錯write() argument must be str, not bytes,主要原因是python2和python3中對‘bytes’和‘str’的處理不同

而且在調試中還不能直接顯示,我是在公眾號平臺中的運維中心發現的,

因為這個問題,耗費了我近兩天的時間來找出解決辦法,

網上的信息太少,為此,我基本把web的源代碼看了一半,為了理解代碼的處理邏輯。

吐槽完了,心裡舒服了,我們繼續進行本期文章

消息加密

首先說明一下,用python來實現公眾號消息加密,在網絡中的資料特別少,基本上都是放一些基礎的知識,就像我的第一期文章那樣,

所以,你看到我的分享,並用於實現公眾號的開發中,是非常有用的。

開始我以為資料少,是因為大家都很容易處理,結果我就碰到上面吐槽的兩大坑了。

官網找資料

消息加密,當然需要在官網資料中找找, 我們唯一能發現的地方就是如下圖

我的公眾號開發(第五步)python實現公眾號消息加密

資料只有右邊紅框中的介紹,最下方有個示例代碼,我們下載後,

我的公眾號開發(第五步)python實現公眾號消息加密

得到這五個文件夾,我們當然是選用python,注意,這個示例代碼是用python2寫成的,我們需轉為python3,才能使用

我的公眾號開發(第五步)python實現公眾號消息加密

打開後一共有四個文件,"pycache"是修改後生成的緩存文件

經過分析後,主要有三個功能文件:

1、ierror.py 定義各種錯誤編號的文件,不用改

2、WXBizMsgCrypt.py 重要功能文件,也是唯一需要轉換為python3的文件

3、Sample.py 測試文件,不用改,我們將WXBizMsgCrypt.py文件轉換後,用來測試是否成功的

這裡,我就直接把已經轉換過WXBizMsgCrypt.py文件貼出來,代碼有點長,我們後面分析

我的公眾號開發(第五步)python實現公眾號消息加密

我的公眾號開發(第五步)python實現公眾號消息加密

我的公眾號開發(第五步)python實現公眾號消息加密

我的公眾號開發(第五步)python實現公眾號消息加密

我的公眾號開發(第五步)python實現公眾號消息加密

我的公眾號開發(第五步)python實現公眾號消息加密

我的公眾號開發(第五步)python實現公眾號消息加密

我的公眾號開發(第五步)python實現公眾號消息加密

我的公眾號開發(第五步)python實現公眾號消息加密

從上面代碼中,我來分析給大家聽聽:

1、class WXBizMsgCrypt(object) 這個是我們後面主要調用的類,生成它的實例來完成加密和解密的事

2、 DecryptMsg WXBizMsgCrypt類中的解密方法,當服務器收到加密的消息體後,我們就用這個來進行解密

3、 EncryptMsg WXBizMsgCrypt類中的加密方法,當我們處理好回覆消息體,就用這個方法來進行加密

4、 class XMLParse 這個類是用來處理消息體加解密的,返回的也是相應的消息體,“extract”、“generate”這兩個就是相應的加解密的方法

5、 class PKCS7Encoder和class Prpcrypt 這兩個類是做加密算法的,不用太關注

6、 class SHA1 這個類是用來對收到的加密消息體做驗證的,驗證通過,才會進行後續的處理

這麼一大段代碼,通過上面的分析之後,你是不是已經很清楚這個文件的邏輯了。

好了, 我們處理完示例文件的轉換工作後,然後我們用Sample.py來驗證一下,

我的公眾號開發(第五步)python實現公眾號消息加密

輸出沒有問題,很好,那我們需要將代碼改造到項目中。

那麼後面該進行什麼呢?

按照資料來說,進展不下去了, 這也就是我遇到的第一個坑。

通過對官網資料一個字一個字的研究,發現兩個詞很關鍵——接入指引技術方案

順著這個線索,我最終在開發平臺裡面的第三方平臺標籤下找到了,如下圖

我的公眾號開發(第五步)python實現公眾號消息加密

上天不負眼神好的人啊,終於被我找到了。咳咳咳,說笑了。

我們繼續看接入指引技術方案兩篇內容,這裡不再截圖,大家可以仔細研究一下

我說一下個人的理解,收到加密消息體後,進行消息體驗證,簽名驗證通過後,解密消息體,然後成了正常的消息體

再進行我們原來的操作, 得到正常的回覆消息體後,再對回覆消息體進行加密,發送即可

這裡驗證消息體簽名,需要用到“msg_signature“、”timetamp“、”nonce”,這三個參數,以及加密消息體本身

而這三個參數,直接可以從url鏈接中就能得到,就像我們最開始做token驗證一樣

好簡單啊,我們只要在原來項目前面做下驗證與解密,最後做下加密工作,就可以了(事後發現,小夥,你想的太簡單了。

那我們開始操作吧。

驗證與解密

首先,我們來做驗證與解密,細心的朋友,在上面大段代碼分析中已經看到,裡面有個class SHA1類,直接做了驗證工作

我們只需要傳進行參數就可以了,這四個參數就是技術文檔說的“msg_signature“、”timetamp“、”nonce”,以及加密消息體本身

(事後註釋:以下操作有錯誤的,大家可以看看逗比過程!〜)

我們直接進Handle類中的POST方法進行更改

我的公眾號開發(第五步)python實現公眾號消息加密

首先是在__init__中增加三個設置,三個值在公眾號後臺-基本配置裡面,如下圖

我的公眾號開發(第五步)python實現公眾號消息加密

將三個值增加到代碼中,後面註釋中已經說明了,當然這裡我已經調為“安全模式”了,如果你還沒有更改,可以在修改配置中改過來。

經過上面的代碼改造,我們來測試一下,看看消息加密後,回覆消息是否正常

(事後註釋:因為代碼是錯的,所以省略回覆的部分,直接進入測試環節)

很顯然,是不正確的,當我使用'python3 main.py 80'重啟服務後,使用手機發送,情況是這樣的

我的公眾號開發(第五步)python實現公眾號消息加密

還有好幾頁呢,全屏的“服務出現故障,稍後重試”,按照技術文檔寫的,應該沒有問題啊

日誌文件中也沒有報錯,只是原來能打印出信息,現在沒有打印出來

經過半天的測試摸索,終於在公眾號後臺的運維中心找到的原因。

我的公眾號開發(第五步)python實現公眾號消息加密

這裡都是記錄消息回覆出錯的地方,我們點進去看看,出現什麼錯誤:

我的公眾號開發(第五步)python實現公眾號消息加密

我將私密信息隱藏了,紅塊有點多,大家主要看箭頭所指的地方

錯誤顯示是write() argument must be str, not bytes,也就是說“bytes”、“str”兩個類型弄錯了。

然後,我經過無數嘗試,什麼“bytes”類型轉為“str”類型等,發現還沒有解決

百度,csdn,cnblog,簡書,stackoverflow,知乎,V2EX。。。可能你能想到的地方,都找了一下這個問題的原因

大部分都是說的文件讀取的事,與我們沒什麼關係。

最後通過DEBUG,發現主要問題出現在web.input(),本身是想用它來獲取url上的參數

結果什麼都沒有得到,查看web官網的介紹,沒有什麼問題啊

然後開始研究web的源代碼,找到input和data的代碼, 發現是在webapi文件中的,

然後看webapi文件,以及相關的cgi文件,utils文件等等

最後發現有個東西可以得到我想要的url參數,就是"web.ctx.env",裡面是post中的各種信息。

當然我還是希望能用更好的辦法來進行,最後在web的github中的“issue”中發現了問題所在

我的公眾號開發(第五步)python實現公眾號消息加密

看到沒,最上面一條就是這個問題,而且是幾個小時前剛發佈的,然後我在closed裡面也找到幾條類似問題

你說為了寫一篇文章,我容易嗎?這裡終於發現了問題

通過“issue”中的說明,發現原來是python2和python3的版本問題

“bytes”、“str”在python2中不用指明,但在python3中必須指明,否則就會報出上面的錯誤

也給出瞭解決辦法,就是修改源文件,在裡面繼承“FieldStorage”類,再改寫其中的“make_file”方法

正確的代碼改造

上面方法也比較容易,但是改寫源代碼,意味著通用性不高,比如我要將這個項目複製到另一個公眾號上

我還要改寫web.py的源代碼,才能使用,這樣不太好,

為了代碼的普適性,所以我就使用上面發現的"web.ctx.env"來進行,無非是自己從url中提取想要的信息嘛,這都不是事〜狗臉

確定好了方向,我們來進行代碼改造,開始動手吧

依然是針對Handle類的POST方法進行改造

我的公眾號開發(第五步)python實現公眾號消息加密

代碼分析:

1、web.ctx.env,這段獲取的是POST的信息包中‘env’部分,裡面包含了很多信息,我們需要取URL,這段正好在'QUERY_STRING'中

我們可以看到各參數是由‘&’來聯接的,所以這裡把每個參數分出來,並轉換為字典,方便取出,如下方

我的公眾號開發(第五步)python實現公眾號消息加密

2、crypt是"WXBizMsgCrypt"的實例化,然後調用“DecryptMsg”方法,來進行消息體的驗證及解密,獲得解密的消息體

3、如代碼中註釋提到,如果解密失敗,“decryp_data”返回為“None”,如果直接傳給recMsg,會出現出錯,

所以需要轉換為空字符串,這樣程序正確進行下去,只是“暫時不處理”

回覆消息體加密

前面是做消息體驗證及解密,經過Handle程序處理後,我們得到了回覆消息體,現在進行回覆體加密

再發送給微信端,這樣粉絲才會收到相應的回覆。

而得到回覆消息體是在“replyMsg.send()”中返回後,直接發送給微信端

有兩種辦法可以解決:

1、直接在Handle每個回覆的地方,將返回的回覆消息體,執行加密後,再發送給微信端

2、在“reply”中的"send()"方法內進行加密處理,只需要傳入兩個參數即可

我在這裡演示第二種方法,首先在Handle中進行改造

只需要將

所有的“replyMsg.send()”,改為“replyMsg.send(crypt, nonce)”即可,傳入兩個必須的參數

然後在“reply”中的所有"send()"方法進行改造

我的公眾號開發(第五步)python實現公眾號消息加密

保存後,執行“nohup python3 main.py 80 > wx.log 2>&1 &”,服務啟動,測試一下,如下圖:

我的公眾號開發(第五步)python實現公眾號消息加密

灰常Good~調用數據庫的關鍵字回覆,和調用智能機器人回覆,都是能得到很好的演示

使用python來實現公眾號的消息加密,就達到了我們的目標。

後續工作

到目前為止,我們擁有一個完整功能,並且消息安全加密的公眾號,後面就能很好的開始運營公眾號。

比如需要增加更多的關鍵字回覆,就將其添加到數據庫中,基本上不用重啟服務器,直接添加就好。

比如需要修改關注後的回覆,直接改動就可以,也不用重啟服務器

比如需要優化智能AI機器人,按照第三期中的內容,來進行操作即可

寫更多的優質原創文章,實驗更多的小項目,與粉絲更多的互動,這些都是更重要的事情。

當然,如果你擁有更多的權限,其實可以做更多有趣的事:

比如使用網頁授權,來進行WEB開發

比如使用素材權限,來進行圖文管理,發佈新圖文的文章

比如使用主動消息權限,來進行客服消息,或是模板消息發佈

比如使用自定義菜單權限,來進行更有趣的菜單實現

等等等等。。。你都能繼續深入研究。

很高興,您能一直陪著,看完成這五期的文章,謝謝你們。

之後,我還會帶來更多新的原創實驗項目,同時也會分享一些個人學習python的心得體會,以及遇到的一些優秀的python庫。

本次的實驗項目——公眾號開發——在此完結。如果您喜歡這期文章,請點贊,支持一下。

歡迎您關注公眾號:JiawuLab,體驗完整功能,或者給我留言,說說你遇到的問題,我們一起探討。

我的公眾號開發(第五步)python實現公眾號消息加密


分享到:


相關文章: