登陆接口
登陆验证,在web开发中算是很常见的东西了,关于这个东西,也不做过多解释了,我这里并没有使用cookie和session,使用了jwt,关于这个,在go官方的网址,下载即可
go get github.com/dgrijalva/jwt-go
步骤也很简单,用密钥加密,然后返回给前端,前端访问其他接口的时候,通过中间件验证此token来确定用户身份。
所以,我们需要写一个加密函数。在middleware/jwt.go
。首先去随便写一个jwt的key,也就是加密密钥,在config.ini中添加即可。然后和其他参数一样,在settings中解析。
/*
config.ini
*/
[server]
JwtKey = +d0(4=-$hy(cdl$tu^@509r#t$e60-1&v$
var JwtKey = []byte(utils.JwtKey)
var code int
type MyClaims struct {
Username string `json:"username"`
jwt.StandardClaims
}
// 生成token
func SetToken(username string) (string, int) {
// 过期时间
expirTime := time.Now().Add(10 * time.Hour)
SetClaims := MyClaims{
username,
jwt.StandardClaims{
// 过期时间
ExpiresAt: expirTime.Unix(),
// 签发人
Issuer: "Salmon",
},
}
// 参数:签发方法,签发命令
reClaim := jwt.NewWithClaims(jwt.SigningMethodHS256, SetClaims)
// 加签
token,err := reClaim.SignedString(JwtKey)
if err != nil{
return "",errmsg.ERROR
}
return token,errmsg.SUCCSE
}
然后就是解密函数
// 验证token
func CheckToken(token string) (*MyClaims, int) {
settoken,_ := jwt.ParseWithClaims(token, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
return JwtKey,nil
})
if key,_ := settoken.Claims.(*MyClaims); settoken.Valid{
return key,errmsg.SUCCSE
}else {
return nil,errmsg.ERROR
}
}
最后把他写成一个中间件。
// jwt中间件
func JwtToken() gin.HandlerFunc{
return func(c *gin.Context) {
// 固定格式
tokenHeader := c.Request.Header.Get("Authorizathion")
// 如果没有带token,则返回一个错误。
if tokenHeader == ""{
code = errmsg.ERROR_TOKEN_EXIST
//c.Abort()
}
// 分割参数
checkToken := strings.SplitN(tokenHeader, " ", 2)
if len(checkToken) != 2 && checkToken[0] != "Bearer" {
code = errmsg.ERROR_TOKEN_TYPE_WRONG
c.Abort()
}
// 解析token方法
key,Tcode := CheckToken(checkToken[1])
if Tcode == errmsg.ERROR {
code = errmsg.ERROR_TOKEN_WRONG
c.Abort()
}
// 如果过期,则返回错误
if time.Now().Unix() > key.ExpiresAt{
code = errmsg.ERROR_TOKEN_RUNTIME
c.Abort()
}
c.JSON(http.StatusOK, gin.H{
"code":code,
"msg":errmsg.GetErrorMsg(code),
})
c.Set("username", key.Username)
c.Next()
}
}
API接口:
func Login(c *gin.Context) {
var formData model.User
_ = c.ShouldBindJSON(&formData)
var token string
var code int
// 验证用户名密码
formData, code = model.CheckLogin(formData.Username, formData.Password)
if code == errmsg.SUCCSE{
// 成功则签发token
token, code = middleware.SetToken(formData.Username)
}
c.JSON(http.StatusOK, gin.H{
"status": code,
"message": errmsg.GetErrorMsg(code),
"token": token,
})
}
最后把路由组给搞一下,注册一下中间件routes/router.go
package routes
import (
v1 "blog/api/v1"
"blog/middleware"
"blog/utils"
"github.com/gin-gonic/gin"
)
func InitRouter() {
gin.SetMode(utils.AppMode)
r := gin.Default()
Auth := r.Group("")
Auth.Use(middleware.JwtToken())
{
// User模块的路由接口
Auth.PUT("user/:id/", v1.EditUser)
Auth.DELETE("user/:id/", v1.DeleteUser)
// Category模块的路由接口
Auth.POST("category/", v1.AddCategory)
Auth.PUT("category/:id/", v1.EditCategory)
Auth.DELETE("category/:id/", v1.DeleteCategory)
// Article模块的路由接口
Auth.POST("article/", v1.AddArticle)
Auth.PUT("article/:id/", v1.EditArticle)
Auth.DELETE("article/:id/", v1.DeleteArticle)
}
router := r.Group("api/v1")
{
router.GET("user/", v1.GetUsers)
Auth.POST("user/", v1.AddUser)
router.POST("login/", v1.Login)
router.GET("category/", v1.GetCategorys)
router.GET("category/:id/", v1.GetCateInfo)
router.GET("article/", v1.GetArticles)
router.GET("article/:id/", v1.GetArticleInfo)
router.GET("catelist/:id/", v1.GetCateArt)
}
_ = r.Run(utils.HttpPort)
}
文件上传
关于文件上传,我选择使用seaweedfs,这是一个很牛掰的文件存储系统,并且他也是使用go写的,所以,都是一家人,地址,最后再使用docker一部署,go的一揽子服务。奈斯。
关于部署seaweedfs和连接,请查看拙作seaweedfs部署详解+部署生产,这里的函数等都是我搭配着gin来使用的,在耦合方面没有什么难度。
package v1
import (
"blog/utils"
"blog/utils/errmsg"
"blog/utils/goseaweed"
"bytes"
"github.com/gin-gonic/gin"
"io"
"log"
"net/http"
"time"
)
// 上传文件
func UploadFile(c *gin.Context){
file, _, _ := c.Request.FormFile("file")
// 初始化
fs := goseaweed.NewSeaweedFs(utils.SeaweedAddress, time.Second * 10)
code = errmsg.SUCCSE
// 转换数据类型为bytes
buf := bytes.NewBuffer(nil)
if _, err := io.Copy(buf, file); err != nil {
code = errmsg.ERROR
}
fid,err := fs.UploadFile("submit",buf.Bytes())
// 上传文件
if err != nil {
log.Fatalln(err)
}
c.JSON(http.StatusOK,gin.H{
"code":code,
"msg": errmsg.GetErrorMsg(code),
"data": fid,
})
}
后端接口方面还有诸多问题,不过我以实现功能为目的,先暂时这样,之后再慢慢补充。
未完待续….
- Post link: https://www.godhearing.cn/gin-vue-da-jian-ge-ren-bo-ke-4/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.