API是什么
API ( Application Programming Interface ,应用程序编程接口)是一些预先定义的函数或者接口,目的是提供应用 程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无须访问源码,或理解内部工作机制的细节。 要实现一个 API 服务器,首先要考虑两个方面: API 风格和媒体类型 。 Go 语言中常用的 API 风格是 RPC 和 REST ,常用的媒体类型是 JSON 、 XML 和 Protobuf 。 在 Go API 开发中常用的组合是 gRPC + Protobuf 和 REST + JSON 。
REST简介
REST 代表表现层状态转移( REpresentational State Transfer ),由 Roy Fielding 在他的论文中提出。 REST 是一 种软件架构风格,不是技术框架,REST 有一系列规范,满足这些规范的 API 均可称为 RESTful API 。 REST 规范中有 如下几个核心:
- REST 中一切实体都被抽象成资源,每个资源有一个唯一的标识 —— URI ,所有的行为都应该是在资源上的 CRUD 操作
- 使用标准的方法 (GET/POST/PUT/DELETE) 来更改资源的状态,常见的操作有:资源的增删改查操作
- 无状态:这里的无状态是指每个 RESTful API 请求都包含了所有足够完成本次操作的信息,服务器端无须保持 Session 无状态对于服务端的弹性扩容是很重要的。 REST 风格虽然适用于很多传输协议,但在实际开发中, REST 由于天生和 HTTP 协议相辅相成,因此 HTTP 协议已经 成了实现 RESTful API 事实上的标准。在 HTTP 协议中通过 POST 、 DELETE 、 PUT 、 GET 方法来对应 REST 资源的
构建API接口
goCopy code
package main
import (
"fmt"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello")
}
func main() {
http.HandleFunc("/hello", helloHandler)
http.ListenAndServe(":8080", nil)
}
用户认证
用户认证是确认用户身份的过程,确保只有合法用户可以访问你的服务。在API开放给公众使用时,用户认证尤为重要,防止未经授权的访问和滥用。
完整代码:
package router
import (
"jwt-go"
"gin"
"time"
)
type LoginInfo struct {
UserName string `json:"user_name"`
Password string `json:"password"`
}
type JWTClaims struct { // token里面添加用户信息,验证token后可能会用到用户信息
jwt.StandardClaims
UserID int `json:"user_id"`
Password string `json:"password"`
Username string `json:"username"`
FullName string `json:"full_name"`
Permissions []string `json:"permissions"`
}
var (
Secret = "zyc" // 加盐
ExpireTime = 3600*24 // token有效期
)
//登录
func Login(c *gin.Context) {
var loginRequest LoginInfo
err := c.Bind(&loginRequest)
if err != nil {
c.JSON(400,err.Error())
return
}
//模拟用户认证
if loginRequest.UserName != "zyc" || loginRequest.Password != "zycqsn" {
c.JSON(401,gin.H{"err":"账号或密码错误"})
return
}
claims := &JWTClaims{
UserID: 1,
Username: loginRequest.UserName,
Password: loginRequest.Password,
FullName: loginRequest.UserName,
Permissions: []string{},
}
claims.IssuedAt = time.Now().Unix()
claims.ExpiresAt = time.Now().Add(time.Second * time.Duration(ExpireTime)).Unix()
signedToken,err:=getToken(claims)
if err!=nil {
c.JSON(400,err.Error())
return
}
//fmt.Printf(signedToken)
c.JSON(200, gin.H{"token": signedToken})
}
//身份验证
func Verify(c *gin.Context)(result bool,userName string,err error) {
strToken,err := c.Cookie("Crow")
if strToken == ""{
result = false
return result,"",nil
}
claim,err := verifyAction(strToken)
if err != nil {
result = false
return result,"",nil
}
result = true
userName = claim.Username
return result,userName,nil
}
//刷新token
func Refresh(c *gin.Context) {
strToken,err := c.Cookie("Crow")
claims,err := verifyAction(strToken)
if err != nil {
c.JSON(400,gin.H{"err":err.Error()})
return
}
claims.ExpiresAt = time.Now().Unix() + (claims.ExpiresAt - claims.IssuedAt)
signedToken,err:=getToken(claims)
if err!=nil{
c.JSON(400,gin.H{"err":err.Error()})
return
}
c.JSON(200,gin.H{"data": signedToken })
}
//验证token是否存在,存在则获取信息
func verifyAction(strToken string) (claims *JWTClaims,err error) {
token, err := jwt.ParseWithClaims(strToken, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(Secret), nil
})
if err != nil {
return nil, err
}
claims, ok := token.Claims.(*JWTClaims)
if !ok {
return nil, err
}
if err := token.Claims.Valid(); err != nil {
return nil, err
}
return claims, nil
}
//生成token
func getToken(claims *JWTClaims)(signedToken string,err error){
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
signedToken, err = token.SignedString([]byte(Secret))
if err != nil {
return "",err
}
return signedToken,nil
}