动态

详情 返回 返回

go-zero jwt 鑑權快速實戰 - 动态 详情

前面我們分享了 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

先來看看基本的代碼目錄

  1. 新建代碼目錄,並編寫 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 .
  1. 編寫數據庫的 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 部分
  1. 修改 my_test_demo/my_book_sys/user/api/etc/user-api.yaml ,加上數據庫配置和 Auth 配置
  • DataSource 數據庫配置

<!---->

  • Auth jwt 配置

    • AccessSecret jwt 需要的密鑰
    • AccessExpire 過期時間,單位 秒
  1. 修改 my_test_demo/my_book_sys/user/api/internal/config/config.go 增加配置對應的數據結構

  1. 補充 svc 層的數據結構,修改 my_test_demo/my_book_sys/user/api/internal/svc/servicecontext.go ,以及補充 NewServiceContext 的實現

  1. 補充咱們的核心邏輯層的代碼,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 部分
  1. 修改 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
  1. 同理,添加配置對應的數據結構,修改 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
   }
}
  1. 補充 svc 層的數據結構,修改 my_test_demo/my_book_sys/book/api/internal/svc/servicecontext.go ,以及補充 NewServiceContext 的實現

  1. 補充咱們的核心邏輯層的代碼,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:

  1. 咱們先來請求 book 的 api,在沒有登錄系統的情況下來查詢書籍,看看是什麼樣的效果
curl -i -X GET \
  'http://localhost:9001/search/do?name=effective%20go'

  1. 很明顯,服務給我們返回了一個未授權,説明咱們的鑑權機制此處是有效果的,那麼接下來登錄一個用户
// 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"
}'
user avatar ecomools 头像 wxp686 头像
点赞 2 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.