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 }
项目代码链接:点我