前面我們分享了 go-zero 的快速實戰以及日誌組件的剖析,本次我們來實戰使用 go-zero jwt 鑑權
本次文章主要是分享關於 go-zero 中 jwt 的使用方式,會以一個 demo 的方式來進行實戰,對於使用 goctl 工具以及安裝細節就不在贅述,有需要的話可以查看:
本次文章主要分為如下幾個部分:
- Jwt 的簡單介紹
<!---->
- Go-zero 中使用 jwt 實戰
Jwt 的簡單介紹
關於 jwt 鑑權的細節和原理,感興趣的朋友可以查看歷史文章:JWT身份認證(附帶源碼講解) | GO主題月
那麼我們如何識別什麼時候需要使用 jwt 呢?
- 用於授權
例如某個系統通過例如賬號密碼登錄之後,後台會生成一個 jwt,這個用户在這個系統之後的任何操作,都會去校驗這個 jwt,就不需要用户操作系統內其他模塊的時候,還去進行一次登錄
當然,這是需要我們做好設定,這個 jwt 針對哪一些路由可以使用,從而允許用户訪問該令牌允許的路由,服務和資源
- 用於信息交換
因為 jwt 可以與各方進行安全的傳輸,內部使用了簽名算法,公鑰加密,私鑰解密,而且 jwt 的數據各種中有標頭,有效載荷,以及其他的簽發時間,過期時間,頒發人等等,可以用來校驗信息是否被篡改了
Go-zero 中使用 jwt 實戰
話不多説,咱們就來開始實戰吧,先來給自己提一個需求:
需求
- 同學們平時去圖書館,都是需要登錄自己的賬號,才可以進入系統查詢書籍餘量的
<!---->
- 那麼我們就來實現一下,用賬號密碼登錄圖書系統,並生成一個 jwt,後續該用户進行書籍查詢的時候,就可以直接使用 jwt 來進行鑑權
分析
那麼,根據上述需求,顯然,咱們會使用到數據庫,本次這裏咱們仍然使用 mysql 進行演示,並且會涉及到用户表和圖書表
我們可以現在創建一下這兩張表
- user table
user.sql
CREATE TABLE `user`
(
`stu_id` varchar(255) NOT NULL COMMENT 'stu_id',
`name` varchar(255) NOT NULL COMMENT 'name',
`password` varchar(255) NOT NULL COMMENT 'password',
`gender` varchar(255) NOT NULL COMMENT 'gender',
PRIMARY KEY(`stu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
| stu_id | 學號 |
|---|---|
| name | 姓名 |
| password | 密碼 |
| gender | 性別 |
- book table
book.sql
CREATE TABLE `book`
(
`book_id` varchar(255) NOT NULL COMMENT 'stu_id',
`name` varchar(255) NOT NULL COMMENT 'name',
`count` INTEGER (255) NOT NULL COMMENT 'password',
PRIMARY KEY(`book_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
| book_id | 圖書 id |
|---|---|
| name | 圖書名稱 |
| count | 圖書剩餘數量 |
咱們可以向表中插入一些 demo 數據,便於後續使用
insert into book(book_id,name,count)values("000001","kubernetes in action",99);
insert into book(book_id,name,count)values("000002","effective go",88);
insert into book(book_id,name,count)values("000003","窮爸爸富爸爸",21);
insert into user(stu_id,name,password,gender)values("13141549", "小胖", "Aa123123", "男");
insert into user(stu_id,name,password,gender)values("15161766", "阿強", "6r*,oo", "男");
insert into user(stu_id,name,password,gender)values("1325590", "marry", "123456", "女");
開始實戰 go-zero 的 jwt
先來看看基本的代碼目錄
- 新建代碼目錄,並編寫 book 和 user 的 api
新建目錄
mkdir my_test_demo/my_book_sys/book/api -p
mkdir my_test_demo/my_book_sys/book/model -p
mkdir my_test_demo/my_book_sys/user/api -p
mkdir my_test_demo/my_book_sys/user/rpc -p
mkdir my_test_demo/my_book_sys/user/model -p
cd my_test_demo
go mod init my_test_demo
go mod tidy
編寫 api 文件 並生成 go 代碼
book.api
定義 book api
-
GET /search/do 查詢書籍接口,使用
jwt: Auth進行標識- 通過請求書名,鑑權完畢之後,響應響應書名對應的剩餘數量
user.api
定義 user api
-
定義 POST /user/login 接口
- 通過賬號密碼請求接口,內部校驗完畢之後,返回 jwt token
\
使用工具將上述 api 生成 go 對應的代碼
cd my_test_demo/my_book_sys/book/api
vim book.api
goctl api go -api book.api -dir .
cd my_test_demo/my_book_sys/user/api
vim user.api
goctl api go -api user.api -dir .
- 編寫數據庫的 sql 語句,使用 goctl 生成 go 代碼
- 直接將上述的
book.sql** 拷貝到my_test_demo/my_book_sys/book/model下
<!---->
- 將 user.sql 拷貝到 **
my_test_demo/my_book_sys/user/model下
生成數據庫相關的 go 代碼文件
cd my_test_demo/my_book_sys/book/model
goctl model mysql ddl -src book.sql -dir .
cd my_test_demo/my_book_sys/user/model
goctl model mysql ddl -src user.sql -dir .
這個時候,咱們就已經完成了大部分的準備工作,接下來我們來查看一下代碼目錄
添加數據庫配置和 jwt 相關配置
User 部分
- 修改
my_test_demo/my_book_sys/user/api/etc/user-api.yaml,加上數據庫配置和 Auth 配置
- DataSource 數據庫配置
<!---->
-
Auth jwt 配置
- AccessSecret jwt 需要的密鑰
- AccessExpire 過期時間,單位 秒
- 修改
my_test_demo/my_book_sys/user/api/internal/config/config.go增加配置對應的數據結構
- 補充 svc 層的數據結構,修改
my_test_demo/my_book_sys/user/api/internal/svc/servicecontext.go,以及補充 NewServiceContext 的實現
- 補充咱們的核心邏輯層的代碼,
my_test_demo/my_book_sys/user/api/internal/logic/loginlogic.go,大體邏輯如下
- 校驗入參,去掉輸入的用户名和密碼的前後空格
<!---->
- 查詢數據庫進行數據校驗,此處我們手動在
my_test_demo/my_book_sys/user/model/usermodel_gen.go文件中添加了數據庫操作的 FindOneByName 方法
<!---->
- 校驗通過之後生成 jwt token 進行響應
此處的 model 方法可以加在 my_test_demo/my_book_sys/user/model/usermodel_gen.go
Book 部分
- 修改
my_test_demo/my_book_sys/book/api/etc/book-api.yaml,加上數據庫配置和 Auth 配置
其中 AccessSecret 和 AccessExpire 的字段名和值保持和上述 user 路徑下的內容一致
Name: search-api
Host: 0.0.0.0
Port: 9001
DataSource: root:123456@tcp(localhost:3306)/test_demo
Auth:
AccessSecret: secretoooppppoooo
AccessExpire: 3600
- 同理,添加配置對應的數據結構,修改
my_test_demo/my_book_sys/book/api/internal/config/config.go
type Config struct {
rest.RestConf
DataSource string
Auth struct {
AccessSecret string
AccessExpire int64
}
}
- 補充 svc 層的數據結構,修改
my_test_demo/my_book_sys/book/api/internal/svc/servicecontext.go,以及補充 NewServiceContext 的實現
- 補充咱們的核心邏輯層的代碼,
my_test_demo/my_book_sys/book/api/internal/logic/searchlogic.go,大體邏輯如下
- 通過書名查詢數據庫
<!---->
- 返回具體書名的剩餘數量
上述代碼中 l.svcCtx.BookHttpModel.FindOneByName 是我們自定義修改了 model 下的文件內容,新增 FindOneByName 方法 ,修改 my_test_demo/my_book_sys/book/model/bookmodel_gen.go
驗收成果
咱們分別進入到項目對應的 api 路徑下,啓動服務
終端1:
cd my_test_demo/my_book_sys/book/api
go run search.go
終端2:
cd my_test_demo/my_book_sys/user/api
go run user.go
終端3:
- 咱們先來請求 book 的 api,在沒有登錄系統的情況下來查詢書籍,看看是什麼樣的效果
curl -i -X GET \
'http://localhost:9001/search/do?name=effective%20go'
- 很明顯,服務給我們返回了一個未授權,説明咱們的鑑權機制此處是有效果的,那麼接下來登錄一個用户
// post 用户登錄
curl -i -X POST http://localhost:9002/user/login -H 'Content-Type: application/json' -d '{
"username":"小胖",
"password":"Aa123123"
}'
可以看到是登錄成功了,且服務端給我們返回了對應的 jwt token,接下來咱們執行第一步,請求查詢一下數據的數量
// get 書籍
curl -i -X GET \
'http://localhost:9001/search/do?name=effective%20go' -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjA5NzMwNDEsImlhdCI6MTY2MDk2OTQ0MSwic3R1SWQiOiIxMzE0MTU0OSJ9.Jae_5GPr-xuB2mfqospfisV93ReUnGTZJ87WsIQ-bhE'
很明顯,此處的鑑權機制 ok,鑑權完畢之後,正確查詢數據庫,查詢到我們期望的書籍剩餘數量
兄弟們,動起手來吧,先來應用 go-zero 的 jwt ,再去看 go-zero 的實際源碼細節,很快就能明白
具體的源碼地址可以查看:https://github.com/qingconglaixueit/my_test_Demo
至此,本篇內容結束
感謝閲讀,歡迎交流,點個贊,關注一波 再走吧
歡迎點贊,關注,收藏
朋友們,你的支持和鼓勵,是我堅持分享,提高質量的動力
好了,本次就到這裏
技術是開放的,我們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。
我是阿兵雲原生,歡迎點贊關注收藏,下次見~
\
\
// get 書籍
curl -i -X GET \
'http://localhost:9001/search/do?name=effective%20go' -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjA5NzMwNDEsImlhdCI6MTY2MDk2OTQ0MSwic3R1SWQiOiIxMzE0MTU0OSJ9.Jae_5GPr-xuB2mfqospfisV93ReUnGTZJ87WsIQ-bhE'
// post 用户登錄
curl -i -X POST http://localhost:9002/user/login -H 'Content-Type: application/json' -d '{
"username":"小胖",
"password":"Aa123123"
}'