gin框架实例


go项目目录结构

main.go

package main1

import (
    gorm "github.com/xdtest/project/database"
    model "github.com/xdtest/project/models"
    routers "github.com/xdtest/project/routers"
)

func main() {
    gorm.Eloquent.AutoMigrate(&model.User{}) //如果数据表结构发生变化自动更新mysql数据库结构
    defer gorm.Eloquent.Close()              //关闭数据库链接
    router := routers.InitRouter()           //指定路由
    router.Run(":8000")                      //在8000端口上运行
}

database/mysql.go

package database

import (
    "fmt"

    _ "github.com/go-sql-driver/mysql" //加载mysql,用他的 init配置  所以前边加的 _
    "github.com/jinzhu/gorm"           //使用gorm来链接和操作数据库
)

var Eloquent *gorm.DB

func init() {
    var err error
    Eloquent, err = gorm.Open("mysql", "root:root1234@tcp(127.0.0.1:3306)/go_test?parseTime=true")

    if err != nil {
        fmt.Printf("mysql connect error %v", err)
    }

    if Eloquent.Error != nil {
        fmt.Printf("database error %v", Eloquent.Error)
    }
}

models/user.go

package models

import (
    "fmt"
    // "log"

    orm "github.com/xdtest/project/database"
)

type User struct {
    Name     string `form:"name",json:"name",bingding:"required",gorm:"unique;not null"`
    Password string `form:"password",json:"password",bingding:"required",gorm:"NOT NULL"`
    Id       int    `form:"id",gorm:"PRIMARY_KEY"`
    Role     int    `gorm:"column:role_id"`
}

func (User) TableName() string {
    return "users"
}

func (u *User) Adduser() (id int, err error) { //user对象的方法 可以直接user.Adduser方法来完成添加记录
    result := orm.Eloquent.Create(&u)
    id = u.Id
    if result.Error != nil {
        err = result.Error
        fmt.Println("这是错误", err, "这是错误")
        fmt.Printf("sdf%d", id)
        return
    }
    return

}

func (u *User) Listusers() (users []User, err error) {

    if err = orm.Eloquent.Find(&users).Error; err != nil {
        return
    }
    return

}

func (u *User) Login() (user1 User, err error) {
    obj := orm.Eloquent.Where("name=? and password=?", u.Name, u.Password).First(&user1)
    if err = obj.Error; err != nil {
        fmt.Printf("这是登陆错误  %v 和 %T", err, err)
        return
    }
    fmt.Println(user1)
    return

}

func (user *User) Deleteuser(id int) (Result User, err error) {
    if err = orm.Eloquent.Select([]string{"id"}).First(&user, id).Error; err != nil {
        return
    }
    if err = orm.Eloquent.Delete(&user).Error; err != nil {
        return
    }
    Result = *user
    return

}

func (user *User) Updatauser(id int) (updatauser User, err error) {
    if err = orm.Eloquent.Select([]string{"id"}).First(&updatauser, id).Error; err != nil {
        return
    }
    if err = orm.Eloquent.Model(&updatauser).Update(&user).Error; err != nil {
        return
    }
    return

}

routers/router.go

package routers

import (
    "io"
    "os"

    "github.com/gin-gonic/gin"
    . "github.com/xdtest/project/apis"
    "github.com/xdtest/project/middleware/jwt"
)

func InitRouter() *gin.Engine {
    f, _ := os.Create("logs/productions.log")
    gin.DefaultWriter = io.MultiWriter(f)

    router := gin.Default()
    v1 := router.Group("/v1")
    v1.Use(jwt.JWTAuth())                              //v1 使用jwt中间件进行前后验证
    router.GET("/user_list_new_handler", Getuserslist) //注意这里调用handler方法直接调用函数名
    router.POST("/register", Addnewuser)               //注意这里调用handler方法直接调用函数名
    router.POST("/login", Userlogin)                   //注意这里调用handler方法直接调用函数名
    router.DELETE("/deleteuser", Deleteuser)           //注意这里调用handler方法直接调用函数名
    v1.POST("/updatauser", Updatauser)                 //注意这里调用handler方法直接调用函数名
    v1.POST("/test", GetDataByTime)                    //使用中间件,验证token, 函数也是验证用户带的token
    return router
}

 

 apis/users.go

package apis

import (
    "fmt"
    "log"
    "net/http"
    "strconv"
    "time"

    jwtgo "github.com/dgrijalva/jwt-go"  //需要安装 然后调用这个jwt-go包
    "github.com/gin-gonic/gin"
    "github.com/xdtest/project/middleware/jwt"
    . "github.com/xdtest/project/models"
)

func Getuserslist(c *gin.Context) {
    var user User
    users, err := user.Listusers()
    if err != nil {
        log.Fatalln(err)
    }
    c.JSON(http.StatusOK, gin.H{
        "msg": users,
    })
}

func Addnewuser(c *gin.Context) {
    var user User
    name := c.Request.FormValue("name")
    password := c.Request.FormValue("password")
    user.Name = name
    user.Password = password
    id, err := user.Adduser()
    if err != nil {
        if err.Error()[:10] == "Error 1062" {
            fmt.Println("ssssss")
            c.JSON(http.StatusOK, gin.H{
                "msg": "用户名已存在",
            })
        }

    } else {
        msg := fmt.Sprintf("创建新的用户成功 用户id为:%d", id)
        c.JSON(http.StatusOK, gin.H{
            "msg": msg,
        })
    }

}

type LoginReq struct {
    Name     string `json:name`
    Password string `json:password`
}

type LoginResult struct {
    User  interface{}
    Token string
}

// 生成令牌  创建jwt风格的token
func GenerateToken(c *gin.Context, user User) {
    j := &jwt.JWT{
        []byte("newtrekWang"),
    }
    claims := jwt.CustomClaims{
        user.Id,
        user.Name,
        user.Password,
        jwtgo.StandardClaims{
            NotBefore: int64(time.Now().Unix() - 1000), // 签名生效时间
            ExpiresAt: int64(time.Now().Unix() + 3600), // 过期时间 一小时
            Issuer:    "newtrekWang",                   //签名的发行者
        },
    }

    token, err := j.CreateToken(claims)

    if err != nil {
        c.JSON(http.StatusOK, gin.H{
            "status": -1,
            "msg":    err.Error(),
        })
        return
    }

    log.Println(token)

    data := LoginResult{
        User:  user,
        Token: token,
    }
    c.JSON(http.StatusOK, gin.H{
        "status": 0,
        "msg":    "登录成功!",
        "data":   data,
    })
    return
}

// GetDataByTime 一个需要token认证的测试接口
func GetDataByTime(c *gin.Context) {
    claims := c.MustGet("claims").(*jwt.CustomClaims)
    if claims != nil {
        c.JSON(http.StatusOK, gin.H{
            "status": 0,
            "msg":    "token有效",
            "data":   claims,
        })
    }
}

func Userlogin(c *gin.Context) {
    var user User
    if c.Bind(&user) == nil { //把form格式传过来的数据绑定到结构体user中去
        msg, err := user.Login()
        if err != nil {
            if err.Error() == "record not found" {
                c.JSON(http.StatusOK, gin.H{
                    "msg":  "用户不存在",
                    "user": nil,
                })
            } else {
                c.JSON(http.StatusOK, gin.H{
                    "msg":  "登陆错误",
                    "user": nil,
                })

            }

        } else {
            GenerateToken(c, msg) //创建token
            // c.JSON(http.StatusOK, gin.H{
            //     "msg":  "登陆成功",
            //     "user": msg,
            // })
        }
    } else {
        c.JSON(400, gin.H{"JSON=== status": "binding JSON error!"})
    }
}

func Deleteuser(c *gin.Context) {
    ids := c.Query("id")
    id, _ := strconv.Atoi(ids)
    var u User
    u.Id = id
    user, err := u.Deleteuser(id)
    if err != nil {
        c.JSON(http.StatusOK, gin.H{
            "msg":  "用户不存在",
            "user": nil,
        })
    } else {
        c.JSON(http.StatusOK, gin.H{
            "msg":  "删除陈工",
            "user": user,
        })
    }
}

func Updatauser(c *gin.Context) {
    ids := c.Query("id")
    name := c.DefaultPostForm("name", "")
    password := c.DefaultPostForm("password", "")

    id, _ := strconv.Atoi(ids)
    var user User
    if name != "" {
        user.Name = name
    }
    if password != "" {
        user.Password = password
    }
    result, err := user.Updatauser(id)
    if err != nil || result.Id == 0 {
        c.JSON(http.StatusOK, gin.H{
            "code":    -1,
            "message": "修改失败",
        })
        return
    }
    c.JSON(http.StatusOK, gin.H{
        "code":    1,
        "message": "修改成功",
    })

}

middleware/jwt/jwt.go  需要jwt验证的直接可以使用这些内容

package jwt

import (
    "errors"
    "fmt"
    "log"
    "net/http"
    "time"

    "github.com/dgrijalva/jwt-go"
    "github.com/gin-gonic/gin"
)

// JWTAuth 中间件,检查token
func JWTAuth() gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.Request.Header.Get("token")
        if token == "" {
            c.JSON(http.StatusOK, gin.H{
                "status": -1,
                "msg":    "请求未携带token,无权限访问",
            })
            c.Abort()
            return
        }

        log.Print("get token: ", token)

        j := NewJWT()
        // parseToken 解析token包含的信息
        claims, err := j.ParseToken(token)
        fmt.Println("claims", claims)
        if err != nil {
            if err == TokenExpired {
                c.JSON(http.StatusOK, gin.H{
                    "status": -1,
                    "msg":    "授权已过期",
                })
                c.Abort()
                return
            }
            c.JSON(http.StatusOK, gin.H{
                "status": -1,
                "msg":    err.Error(),
            })
            c.Abort()
            return
        }
        // 继续交由下一个路由处理,并将解析出的信息传递下去
        c.Set("claims", claims)
    }
}

// JWT 签名结构
type JWT struct {
    SigningKey []byte
}

// 一些常量
var (
    TokenExpired     error  = errors.New("Token is expired")
    TokenNotValidYet error  = errors.New("Token not active yet")
    TokenMalformed   error  = errors.New("That's not even a token")
    TokenInvalid     error  = errors.New("Couldn't handle this token:")
    SignKey          string = "newtrekWang"
)

// 载荷,可以加一些自己需要的信息
type CustomClaims struct {
    ID       int    `json:"userId"`
    Name     string `json:"name"`
    Password string `json:"telephone"`
    jwt.StandardClaims
}

// 新建一个jwt实例
func NewJWT() *JWT {
    return &JWT{
        []byte(GetSignKey()),
    }
}

// 获取signKey
func GetSignKey() string {
    return SignKey
}

// 这是SignKey
func SetSignKey(key string) string {
    SignKey = key
    return SignKey
}

// CreateToken 生成一个token
func (j *JWT) CreateToken(claims CustomClaims) (string, error) {
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString(j.SigningKey)
}

// 解析Tokne
func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) {
    token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
        return j.SigningKey, nil
    })
    if err != nil {
        if ve, ok := err.(*jwt.ValidationError); ok {
            if ve.Errors&jwt.ValidationErrorMalformed != 0 {
                return nil, TokenMalformed
            } else if ve.Errors&jwt.ValidationErrorExpired != 0 {
                // Token is expired
                return nil, TokenExpired
            } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
                return nil, TokenNotValidYet
            } else {
                return nil, TokenInvalid
            }
        }
    }
    if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
        return claims, nil
    }
    return nil, TokenInvalid
}

// 更新token
func (j *JWT) RefreshToken(tokenString string) (string, error) {
    jwt.TimeFunc = func() time.Time {
        return time.Unix(0, 0)
    }
    token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
        return j.SigningKey, nil
    })
    if err != nil {
        return "", err
    }
    if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
        jwt.TimeFunc = time.Now
        claims.StandardClaims.ExpiresAt = time.Now().Add(1 * time.Hour).Unix()
        return j.CreateToken(*claims)
    }
    return "", TokenInvalid
}

 

项目代码链接:点我


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM