如何将我的服务开放给用户:构建 API 接口和用户认证的实践指南 | 青训营

1 构建API接口

1.1 构建基础API

首先,我们必须创建一个非常简单的服务器来处理HTTP请求。为此,我们创建一个名为main.go的新文件。 在这个main.go文件中,我们将要定义3个不同的函数。一个page函数(将处理对我们根URL的所有请求),router函数(将与已定义函数匹配的URL路径匹配)和main函数(将启动我们的API)

go 复制代码
package main

import (
    "fmt"
    "log"
    "net/http"
)

func page(w http.ResponseWriter, r *http.Request){
    fmt.Fprintf(w, "Hello!")
}

func router() {
    http.HandleFunc("/", page)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func main() {
    router()
}

如果我们现在运行,则应该可以看到程序在端口10000上启动(该端口未被其他进程使用)。 打开http://localhost:8080/,应该看到"Hello!" ,现在已经成功创建了一个基础的API。

1.2使用Gin优化接口

安装Gin

arduino 复制代码
go get -u github.com/gin-gonic/gin

过程

  1. 客户端请求服务器
  2. HTTP 服务引擎 http.Server 接收到请求,并初步处理成 http.ResponseWriter 和 http.Request 并传递给注册过的上层请求处理
  3. Handler(实现 ServerHTTP 接口,并注册到 http.ListenAndServe 的 Handler)(即 Gin 的 Engine)
  4. Engine 把请求数据放入 Context pool 中,并传递给 Engine 的 handleHTTPRequest 进行处理
  5. handleHTTPRequest 从 trees 中查找对应的 node,并回调注册过的请求处理 Handler

先初始化

go 复制代码
   // 初始化一个http服务对象
   engine := gin.Default()

设置路由

javascript 复制代码
   // 设置一个get请求的路由,url为localhost
   engine.GET("/", func(c *gin.Context) {
       //获取数据
       //获取handler处理
       //返回数据
      c.String(http.StatusOK, "hello World!")
   })

监听服务

ruby 复制代码
    //监听并启动服务,默认 http://localhost:8080/
   engine.Run()

完善

在真正写服务的时候不可能会一大堆写到一个.go文件中会将文件分为controller包、repository包、util和public等包,public放置静态资源文化,而controller包 中就是进行处理的Handler,再有就是repository包用来连接数据库

而路由的注册我的习惯是写一个router.go文件来统一管理路由

2 用户认证

安装jwt包

go 复制代码
go get github.com/dgrijalva/jwt-go

post请求get请求的区别

  • GET请求会把请求参数拼接到URL后面,而POST请求则是将请求参数放在请求体中发送。因此,GET请求的请求参数会暴露在URL中,而POST请求的请求参数不会。
  • GET请求通常用于请求资源,而POST请求通常用于提交数据。GET请求会向服务器请求一个资源(如HTML页面或者图片),而POST请求则是向服务器提交表单数据或者上传文件等操作。
  • GET请求的请求参数长度受到URL长度限制,通常不能超过2048个字符。而POST请求的参数长度通常没有严格限制,可以传输更大的数据量。
  • GET请求是幂等的,也就是说,多次相同的GET请求返回的结果应该是一样的。而POST请求不是幂等的,即使发送相同的请求数据,每次响应可能都不同。

GET请求适合用于查询数据,POST请求适合于提交数据。

token的组成:

一共由三部分组成:

  1. 协议头(header):token使用的加密协议
  2. 荷载:储存的是token发放时间、发放人、主题等信息
  3. 第三部分:前面两部分+key进行hash的一个值

获取Token

common包下的jwt.go

go 复制代码
package common
 
import (
    "ginTest/model"
    "github.com/dgrijalva/jwt-go"
    "time"
)
 
// 定义一个jwt加密的密钥
var jwtKey = []byte("a_secret_crect")
 
// 定义token的Claims
type Claims struct {
    UserId uint
    jwt.StandardClaims
}
 
// 登录成功之后就调用这个方法来释放token
func ReleaseToken(user model.User) (string, error) {
    //定义token的过期时间:7天
    expirationTime := time.Now().Add(7 * 24 * time.Hour)
    claims := &Claims{
        UserId: user.ID,
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: expirationTime.Unix(),
            IssuedAt:  time.Now().Unix(), //token发放的时间
            Issuer:    "linxi",           //发放人
            Subject:   "user token",      //主题
        },
    }
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    //使用jwt密钥来生成token
    tokenString, err := token.SignedString(jwtKey)
    if err != nil {
        return "", err
    }
    return tokenString, nil
}

controller包的User.go

go 复制代码
package controller

func login(c *gin.Context){
    //发放token   
    token, err := common.ReleaseToken(user)
    if err != nil {
        ctx.JSON(http.StatusInternalServerError, gin.H{"code": 500, "msg": "系统异常"})
        log.Printf("token generate error :%v ", err)
        return
    }
}

Token用户认证

jwt.go中新定义一个函数用来解析token

go 复制代码
// 定义一个函数用来解析token
func ParseToken(tokenString string) (*jwt.Token, *Claims, error) {
    claims := &Claims{}
 
    token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
        return jwtKey, nil
    })
 
    return token, claims, err
}

user.go中返回新信息

css 复制代码
func info(c *gin.Context){
    token := c.get(token)
    _, claims, _ := common.ParseToken(token)
    user = User{
        UserId: claims.UserId,
    }
    c.JSON(httpStatus, gin.H{"code": code, "data": user, "msg": msg})
}
相关推荐
Find3 个月前
MaxKB 集成langchain + Vue + PostgreSQL 的 本地大模型+本地知识库 构建私有大模型 | MarsCode AI刷题
青训营笔记
理tan王子3 个月前
伴学笔记 AI刷题 14.数组元素之和最小化 | 豆包MarsCode AI刷题
青训营笔记
理tan王子3 个月前
伴学笔记 AI刷题 25.DNA序列编辑距离 | 豆包MarsCode AI刷题
青训营笔记
理tan王子3 个月前
伴学笔记 AI刷题 9.超市里的货物架调整 | 豆包MarsCode AI刷题
青训营笔记
夭要7夜宵3 个月前
分而治之,主题分片Partition | 豆包MarsCode AI刷题
青训营笔记
三六3 个月前
刷题漫漫路(二)| 豆包MarsCode AI刷题
青训营笔记
tabzzz3 个月前
突破Zustand的局限性:与React ContentAPI搭配使用
前端·青训营笔记
Serendipity5653 个月前
Go 语言入门指南——单元测试 | 豆包MarsCode AI刷题;
青训营笔记
wml3 个月前
前端实践-使用React实现简单代办事项列表 | 豆包MarsCode AI刷题
青训营笔记
用户44710308932423 个月前
详解前端框架中的设计模式 | 豆包MarsCode AI刷题
青训营笔记