服務計算——簡單web服務與客戶端開發

任務概述

利用 web 客戶端調用遠端服務是服務開發本實驗的重要內容。其中,要點建立 API First 的開發理念,實現前後端分離,使得團隊協作變得更有效率。

任務目標

  1. 選擇合適的 API 風格,實現從接口或資源(領域)建模,到 API 設計的過程
  2. 使用 API 工具,編制 API 描述文件,編譯生成服務器、客戶端原型
  3. 使用 Github 建立一個組織,通過 API 文檔,實現 客戶端項目 與 RESTful 服務項目同步開發
  4. 使用 API 設計工具提供 Mock 服務,兩個團隊獨立測試 API
    使用 travis 測試相關模塊

API風格

我們的API設計遵循了項目文檔中的api.yaml

{
    "ArticlePost": "/openapi101/users/{username}/article",
   	"ArticleArticleIdGet":"/openapi101/users/{username}/article/{article_id}",
    "CreateComment":"/openapi101/users/{username}/article/{article_id}/comment",
    "GetCommentsOfArticle":"/openapi101/users/{username}/article/{article_id}/comment",
    "AuthSigninPost":"/openapi101/auth/signin",
    "AuthSignupPost": "/openapi101/auth/signup"
}

使用API生成原型

使用Swagger Edit工具自動生成框架:

API文檔如下:

swagger: "2.0"
info:
  description: "A simple API to learn how to write OpenAPI Specification"
  version: "1.0.0"
  title: "Simple API"
host: "simple.api"
basePath: "/openapi101"
schemes:
- "https"
paths:
  /auth/signin:
    post:
      summary: "sign in"
      parameters:
      - name: "username"
        in: "path"
        required: true
        type: "string"
        x-exportParamName: "Username"
      responses:
        "200":
          description: "A list of Person"
          schema:
            required:
            - "username"
            properties:
              username:
                type: "string"
        "404":
          description: "The user does not exists"
  /auth/signup:
    post:
      summary: "sign up a user"
      description: "sign up a user"
      parameters:
      - in: "body"
        name: "user"
        required: false
        schema:
          $ref: "#/definitions/user"
        x-exportParamName: "User"
      responses:
        "204":
          description: "OK"
        "400":
          description: "Wrong"
  /article/{article_id}:
    get:
      summary: "get post"
      parameters:
      - name: "article_id"
        in: "path"
        description: "article id"
        required: true
        type: "string"
        x-exportParamName: "ArticleId"
      responses:
        "200":
          description: "A post"
          schema:
            properties:
              name:
                type: "string"
              data:
                type: "string"
  /article:
    post:
      summary: "Create article"
      parameters:
      - in: "body"
        name: "content"
        required: true
        schema:
          $ref: "#/definitions/content"
        x-exportParamName: "Content"
      responses:
        "204":
          description: "A post"
definitions:
  user:
    required:
    - "password"
    - "username"
    properties:
      username:
        type: "string"
      password:
        type: "string"
  content:
    required:
    - "article_content"
    properties:
      article_content:
        type: "string"
      author:
        type: "string"

後端框架

在Swagger Edit編輯器中點擊go-server生成後端框架,結構如下:

- go-server
	- .swagger-codegen
		- VERSION
	- api
		- swagger.yaml  #api設計
	- go
		- routers.go  #路由匹配
		- logger.go   #日誌
		- api_default.go  #api框架
		- user.go
		- user_api.go
		- ...
		- README.md
	- main.go

API實現

框架搭建好後,就需要關注實現部分

註冊實現

在這裏插入圖片描述

登陸實現

在這裏插入圖片描述
數據庫使用到boltdb,相關資料
開啓數據庫:

	db, err := bolt.Open("my.db", 0600, nil)
    if err != nil {
        log.Fatal(err)
    }
	defer db.Close()

數據庫的讀操作:

	err = db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("User"))
		if b != nil {
			v := b.Get([]byte(user.Username))
			if ByteSliceEqual(v, []byte(user.Password)) {
				return nil
			} else {
				return errors.New("Wrong Username or Password")
			}
		} else {
			return errors.New("Wrong Username or Password")
		}
	})

寫操作:

	err = db.Update(func(tx *bolt.Tx) error {
		b, err := tx.CreateBucketIfNotExists([]byte("User"))
		if err != nil {
			return err
		}
		return b.Put([]byte(user.Username), []byte(user.Password))
	})

json的序列化和反序列化:
當服務端收到請求後,需要使用json解析器反序列化爲結構體
當服務端發送響應時,需要將結構體序列化爲字符串

  • json反序列化:

comment := &Comment{
	Date:  time.Now().Format("2006-01-02 15:04:05"),
	Content: "",
	Author: "",
	ArticleId: Id,
}
err = json.NewDecoder(r.Body).Decode(&comment)

JWT認證

JWT是Json Web Token的縮寫

token的意思是“令牌”,是用戶身份的驗證方式,最簡單的token組成:

  • uid(用戶唯一的身份標識)
  • time(當前時間的時間戳)
  • sign(簽名,由token的前幾位+用哈希算法壓縮成一定長的十六進制字符串,可以防止惡意第三方拼接token請求服務器)。
    還可以把不變的參數也放進token,避免多次查庫time(當前時間的時間戳)

JWT認證:
用戶註冊之後, 服務器生成一個 JWT token返回給瀏覽器, 瀏覽器向服務器請求數據時將 JWT token 發給服務器, 服務器用 signature 中定義的方式解碼 JWT 獲取用戶信息.

一個JWT token包含3部分:

  • header: 告訴我們使用的算法和 token 類型
  • Payload:必須使用 sub key 來指定用戶 ID, 還可以包括其他信息比如 email, username 等.
  • Signature: 用來保證 JWT 的真實性. 可以使用不同算法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章