├── config.json
├── .idea
├── misc.xml
├── vcs.xml
├── modules.xml
├── lib-demo.iml
└── workspace.xml
├── datasource
├── tableInit.go
└── datasource.go
├── utils
├── deferutil.go
├── jsonutil.go
├── hmacsha256util.go
└── md5.go
├── models
├── book.go
├── result.go
└── user.go
├── conf
└── sysconfig.go
├── README.md
├── main.go
├── route
└── route.go
├── controllers
├── user_controller.go
└── book_controller.go
├── repo
├── book_repo.go
└── user_repo.go
├── service
├── user_service.go
└── book_service.go
├── middleware
└── jwt.go
└── db
├── test.sql
└── iris-gorm-demo.postman_collection.json
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "Port": "8848",
3 | "DBUserName": "root",
4 | "DBPassword": "123456",
5 | "DBIp": "127.0.0.1",
6 | "DBPort": "3306",
7 | "DBName": "test"
8 | }
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/datasource/tableInit.go:
--------------------------------------------------------------------------------
1 | package datasource
2 |
3 | import (
4 | "../models"
5 | )
6 | // 初始化表 如果不存在该表 则自动创建
7 | func Createtable() {
8 | GetDB().AutoMigrate(
9 | &models.User{},
10 | &models.Book{},
11 | )
12 | }
--------------------------------------------------------------------------------
/utils/deferutil.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "github.com/jinzhu/gorm"
5 | )
6 |
7 | func Defer(tx *gorm.DB, code *int) {
8 | if *code == 0{
9 | //提交事务
10 | tx.Commit()
11 | } else {
12 | //回滚
13 | tx.Rollback()
14 | }
15 | }
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/lib-demo.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/utils/jsonutil.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import "encoding/json"
4 |
5 | //interface{}可以储存任意类型的数值
6 | func JsonEncode(code int, data interface{}, msg string) ([]byte, error) {
7 | result := struct {
8 | Code int
9 | Data interface{}
10 | Msg string
11 | }{code, data, msg}
12 | return json.Marshal(result)
13 | }
14 |
--------------------------------------------------------------------------------
/models/book.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | "github.com/jinzhu/gorm"
5 | )
6 |
7 | type Book struct {
8 | gorm.Model
9 | Name string `gorm:"type:varchar(20);not null;"`
10 | Count string `gorm:"type:varchar(10);not null;"`
11 | Author string `gorm:"type:varchar(20);not null;"`
12 | Type string `gorm:"type:varchar(20);not null;"`
13 | }
14 |
15 |
16 |
--------------------------------------------------------------------------------
/utils/hmacsha256util.go:
--------------------------------------------------------------------------------
1 |
2 | package utils
3 |
4 | import (
5 | "crypto/hmac"
6 | "crypto/sha256"
7 | "encoding/base64"
8 | "encoding/hex"
9 | )
10 |
11 | func HmacSha256Encode(strings string, secret string) string {
12 | key := []byte(secret)
13 | h := hmac.New(sha256.New, key)
14 | h.Write([]byte(strings))
15 | sha := hex.EncodeToString(h.Sum(nil))
16 |
17 | return base64.StdEncoding.EncodeToString([]byte(sha))
18 | }
19 |
--------------------------------------------------------------------------------
/models/result.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | type Result struct {
4 | Code int
5 | Msg string
6 | Data interface{}
7 | }
8 |
9 | func NewResult(data interface{}, c int, m ...string) *Result {
10 | r := &Result{Data: data, Code: c}
11 |
12 | if e, ok := data.(error); ok {
13 | if m == nil {
14 | r.Msg = e.Error()
15 | }
16 | } else {
17 | r.Msg = "SUCCESS"
18 | }
19 | if len(m) > 0 {
20 | r.Msg = m[0]
21 | }
22 |
23 | return r
24 | }
25 |
--------------------------------------------------------------------------------
/models/user.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import "github.com/jinzhu/gorm"
4 |
5 | type User struct {
6 | gorm.Model
7 | Username string `gorm:"unique"`
8 | Password string
9 | Name string //姓名
10 | Email string //邮箱
11 | Mobile string //手机
12 | QQ string
13 | Gender int //0男 1女
14 | Age int //年龄
15 | Remark string //备注
16 | Token string `gorm:"-"`
17 | Session string `gorm:"-"`
18 | }
19 |
--------------------------------------------------------------------------------
/conf/sysconfig.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import (
4 | "github.com/json-iterator/go"
5 | "io/ioutil"
6 | )
7 |
8 | var Sysconfig = &sysconfig{}
9 |
10 | func init() {
11 | //指定对应的json配置文件
12 | b, err := ioutil.ReadFile("config.json")
13 | if err != nil {
14 | panic("Sys config read err")
15 | }
16 | err = jsoniter.Unmarshal(b, Sysconfig)
17 | if err != nil {
18 | panic(err)
19 | }
20 |
21 | }
22 |
23 | type sysconfig struct {
24 | Port string `json:"Port"`
25 | DBUserName string `json:"DBUserName"`
26 | DBPassword string `json:"DBPassword"`
27 | DBIp string `json:"DBIp"`
28 | DBPort string `json:"DBPort"`
29 | DBName string `json:"DBName"`
30 |
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # iris-gorm-demo
2 | 与lib-ui对应的服务端代码,使用iris+gorm+mysql搭建的一个restful项目模板
3 |
4 | #### 12.26更新
5 | 1. 优化代码结构
6 | 2. jwt实现
7 | 3. json传参
8 | 4. md5处理
9 | ```
10 | conf 配置文件
11 | controllers 控制器 入参处理 api的入口
12 | datasource 数据库配置
13 | models 结构体
14 | db sql数据文件 postman接口文件
15 | repo 数据库的操作
16 | middleware 中间件 jwt实现
17 | route 注册路由
18 | service 业务逻辑代码
19 | utils 工具类
20 | config.json 配置文件的映射
21 | main.go 主程序入口
22 | ```
23 | ### 启动项目
24 | ```
25 | 1.安装依赖 go get
26 | 2.go run main.go
27 | ```
28 | 1. 使用go get直接下载依赖,或在github手动下载包放到gopath/src/github.com/
29 | 2. 导包时使用相对路径需要将项目放在你配置的GOPATH目录下
30 | 3. 这里我没有使用go module来管理依赖,是因为下载包很容易被墙。你可以使用go mod init用go mod来管理
31 |
32 | #### 前端
33 | https://github.com/pppercyWang/lib-ui
34 |
--------------------------------------------------------------------------------
/utils/md5.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "crypto/md5"
5 | "crypto/rand"
6 | "encoding/base64"
7 | "encoding/hex"
8 | "io"
9 | )
10 |
11 | func GetMD5String(strings string) string {
12 |
13 | md5Ctx := md5.New()
14 | md5Ctx.Write([]byte(strings))
15 | cipherStr := md5Ctx.Sum(nil)
16 | return hex.EncodeToString(cipherStr)
17 | }
18 | func Md5ByByte(bytes []byte) string {
19 |
20 | md5Ctx := md5.New()
21 | md5Ctx.Write(bytes)
22 | cipherStr := md5Ctx.Sum(nil)
23 | return hex.EncodeToString(cipherStr)
24 | }
25 |
26 | //生成Guid字串
27 | func UniqueId() string {
28 | b := make([]byte, 48)
29 | if _, err := io.ReadFull(rand.Reader, b); err != nil {
30 | return ""
31 | }
32 | return GetMD5String(base64.URLEncoding.EncodeToString(b))
33 | }
34 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "./conf"
5 | "./route"
6 | "flag"
7 | "github.com/iris-contrib/middleware/cors"
8 | "github.com/kataras/iris"
9 | )
10 |
11 | func main() {
12 | flag.Parse()
13 | app := newApp()
14 | route.InitRouter(app)
15 | err := app.Run(iris.Addr(":"+conf.Sysconfig.Port), iris.WithoutServerError(iris.ErrServerClosed))
16 | if err != nil {
17 | panic(err)
18 | }
19 | }
20 |
21 | func newApp() *iris.Application {
22 | app := iris.New()
23 | app.Configure(iris.WithOptimizations)
24 | crs := cors.New(cors.Options{
25 | AllowedOrigins: []string{"*"}, // allows everything, use that to change the hosts.
26 | AllowCredentials: true,
27 | AllowedHeaders: []string{"*"},
28 | })
29 | app.Use(crs)
30 | app.AllowMethods(iris.MethodOptions)
31 | return app
32 | }
33 |
--------------------------------------------------------------------------------
/route/route.go:
--------------------------------------------------------------------------------
1 | package route
2 |
3 | import (
4 | "../controllers"
5 | "github.com/kataras/iris"
6 | "github.com/kataras/iris/mvc"
7 | "net/http"
8 | "../middleware"
9 | )
10 |
11 | func InitRouter(app *iris.Application) {
12 | //app.Use(CrossAccess)
13 | bathUrl := "/api"
14 | mvc.New(app.Party(bathUrl + "/user")).Handle(controllers.NewUserController())
15 | app.Use(middleware.GetJWT().Serve) // jwt
16 | mvc.New(app.Party(bathUrl +"/book")).Handle(controllers.NewBookController())
17 | }
18 |
19 | func CrossAccess11(next http.Handler) http.Handler {
20 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
21 | w.Header().Add("Access-Control-Allow-Origin", "*")
22 | next.ServeHTTP(w, r)
23 | })
24 | }
25 | func CrossAccess(ctx iris.Context) {
26 | ctx.ResponseWriter().Header().Add("Access-Control-Allow-Origin", "*")
27 | }
28 |
--------------------------------------------------------------------------------
/datasource/datasource.go:
--------------------------------------------------------------------------------
1 | package datasource
2 |
3 | import (
4 | "../conf"
5 | _ "github.com/go-sql-driver/mysql"
6 | "github.com/jinzhu/gorm"
7 | "strings"
8 | "time"
9 | )
10 |
11 | var db *gorm.DB
12 |
13 | func GetDB() *gorm.DB {
14 | return db
15 | }
16 |
17 | func init() {
18 | path := strings.Join([]string{conf.Sysconfig.DBUserName, ":", conf.Sysconfig.DBPassword, "@(", conf.Sysconfig.DBIp, ":", conf.Sysconfig.DBPort, ")/", conf.Sysconfig.DBName, "?charset=utf8&parseTime=true"}, "")
19 | var err error
20 | db, err = gorm.Open("mysql", path)
21 | if err !=nil{
22 | panic(err)
23 | }
24 | db.SingularTable(true)
25 | db.DB().SetConnMaxLifetime(1 * time.Second)
26 | db.DB().SetMaxIdleConns(20) //最大打开的连接数
27 | db.DB().SetMaxOpenConns(2000) //设置最大闲置个数
28 | db.SingularTable(true) //表生成结尾不带s
29 | // 启用Logger,显示详细日志
30 | db.LogMode(true)
31 | Createtable();
32 | }
33 |
--------------------------------------------------------------------------------
/controllers/user_controller.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "../models"
5 | "../service"
6 | "github.com/kataras/iris"
7 | "log"
8 | )
9 |
10 | type UserController struct {
11 | Ctx iris.Context
12 | Service service.UserService
13 | }
14 |
15 | func NewUserController() *UserController {
16 | return &UserController{Service: service.NewUserServices()}
17 | }
18 |
19 |
20 | func (g *UserController) PostLogin() models.Result {
21 | var m map[string]string
22 | err := g.Ctx.ReadJSON(&m)
23 | if err != nil {
24 | log.Println("ReadJSON Error:", err)
25 | }
26 | result := g.Service.Login(m)
27 | return result
28 | }
29 |
30 | func (g *UserController) PostSave() (result models.Result) {
31 | var user models.User
32 | if err := g.Ctx.ReadJSON(&user); err != nil {
33 | log.Println(err)
34 | result.Msg = "数据错误"
35 | return
36 | }
37 |
38 | return g.Service.Save(user)
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/repo/book_repo.go:
--------------------------------------------------------------------------------
1 | package repo
2 |
3 | import (
4 | "../datasource"
5 | "../models"
6 | "github.com/spf13/cast"
7 | )
8 | type BookRepository interface {
9 | GetBookList(m map[string]interface{})(total int,books []models.Book)
10 | SaveBook(book models.Book)(err error)
11 | GetBook(id uint)(book models.Book,err error)
12 | DelBook(id uint)(err error)
13 | }
14 | func NewBookRepository() BookRepository{
15 | return &bookRepository{}
16 | }
17 | var db = datasource.GetDB()
18 |
19 | type bookRepository struct {}
20 |
21 | func (n bookRepository) GetBookList(m map[string]interface{})(total int,books []models.Book){
22 | db.Table("book").Count(&total)
23 | err := db.Limit(cast.ToInt(m["size"])).Offset((cast.ToInt(m["page"])-1)*cast.ToInt(m["size"])).Find(&books).Error
24 | if err!=nil {
25 | panic("select Error")
26 | }
27 | return
28 | }
29 | func (n bookRepository) SaveBook(book models.Book)(err error){
30 | if book.ID != 0{
31 | err := db.Save(&book).Error
32 | return err
33 | }else {
34 | err := db.Create(&book).Error
35 | return err
36 | }
37 | }
38 | func (n bookRepository) GetBook(id uint)(book models.Book,err error){
39 | err = db.First(&book,id).Error
40 | return
41 | }
42 | func (n bookRepository) DelBook(id uint)(err error){
43 | var book models.Book
44 | book.ID = id
45 | err = db.Unscoped().Delete(&book).Error //如果直接Delete是软删除
46 | return
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/service/user_service.go:
--------------------------------------------------------------------------------
1 |
2 | package service
3 |
4 | import (
5 | "../models"
6 | "../repo"
7 | "../utils"
8 | "../middleware"
9 | // "fmt"
10 | // "github.com/spf13/cast"
11 | // "log"
12 | )
13 |
14 | type UserService interface {
15 | Login(m map[string]string) (result models.Result)
16 | Save(user models.User) (result models.Result)
17 | }
18 | type userServices struct {
19 |
20 | }
21 |
22 | func NewUserServices() UserService {
23 | return &userServices{}
24 | }
25 |
26 | var userRepo = repo.NewUserRepository()
27 |
28 | /*
29 | 登录
30 | */
31 | func (u userServices) Login(m map[string]string) (result models.Result) {
32 |
33 | if m["username"] == "" {
34 | result.Code = -1
35 | result.Msg = "请输入用户名!"
36 | return
37 | }
38 | if m["password"] == "" {
39 | result.Code = -1
40 | result.Msg = "请输入密码!"
41 | return
42 | }
43 | user := userRepo.GetUserByUserNameAndPwd(m["username"],utils.GetMD5String(m["password"]))
44 | if user.ID == 0 {
45 | result.Code = -1
46 | result.Msg = "用户名或密码错误!"
47 | return
48 | }
49 | user.Token = middleware.GenerateToken(user)
50 | result.Code = 0
51 | result.Data = user
52 | result.Msg = "登录成功"
53 | return
54 | }
55 |
56 | /*
57 | 保存
58 | */
59 | func (u userServices) Save(user models.User) (result models.Result){
60 | //添加
61 | if user.ID == 0 {
62 | agen := userRepo.GetUserByUsername(user.Username)
63 | if agen.ID != 0 {
64 | result.Msg = "登录名重复,保存失败"
65 | return
66 | }
67 | }
68 | code,p := userRepo.Save(user)
69 | if code == -1 {
70 | result.Code = -1;
71 | result.Msg = "保存失败"
72 | return
73 | }
74 | result.Code = 0
75 | result.Data = p
76 | return
77 | }
78 |
79 |
--------------------------------------------------------------------------------
/service/book_service.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "../models"
5 | "../repo"
6 | )
7 | type BookService interface {
8 | GetBookList (m map[string]interface{}) (result models.Result)
9 | SaveBook(book models.Book) (result models.Result)
10 | GetBook(id uint) (result models.Result)
11 | DelBook(id uint) (result models.Result)
12 | }
13 |
14 | type bookService struct {}
15 |
16 | func NewBookService() BookService{
17 | return &bookService{}
18 | }
19 |
20 | var bookRepo = repo.NewBookRepository()
21 |
22 | func (u bookService)GetBookList (m map[string]interface{}) (result models.Result){
23 | total,books := bookRepo.GetBookList(m)
24 | maps := make(map[string]interface{},2)
25 | maps["Total"] = total
26 | maps["List"] = books
27 | result.Data = maps
28 | result.Code = 0
29 | result.Msg ="SUCCESS"
30 | return
31 | }
32 | func (n bookService) SaveBook(book models.Book)(result models.Result){
33 | err := bookRepo.SaveBook(book)
34 | if err != nil{
35 | result.Code = -1
36 | result.Msg ="保存失败"
37 | }else{
38 | result.Code = 1
39 | result.Msg ="保存成功"
40 | }
41 | return
42 | }
43 | func (n bookService) GetBook(id uint)(result models.Result){
44 | book,err := bookRepo.GetBook(id)
45 | if err!= nil{
46 | result.Code = -1
47 | result.Msg = err.Error()
48 | }else{
49 | result.Data = book
50 | result.Code = 0
51 | result.Msg ="SUCCESS"
52 | }
53 | return
54 | }
55 | func (n bookService) DelBook(id uint)(result models.Result){
56 | err := bookRepo.DelBook(id)
57 | if err!= nil{
58 | result.Code = -1
59 | result.Msg = err.Error()
60 | }else{
61 | result.Code = 0
62 | result.Msg ="SUCCESS"
63 | }
64 | return
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/repo/user_repo.go:
--------------------------------------------------------------------------------
1 |
2 | package repo
3 |
4 | import (
5 | "../datasource"
6 | "../models"
7 | "../utils"
8 | // "github.com/spf13/cast"
9 | "log"
10 | )
11 |
12 | type UserRepository interface {
13 | GetUserByUserNameAndPwd(username string, password string) (user models.User)
14 | GetUserByUsername(username string) (user models.User)
15 | Save(user models.User) (int, models.User)
16 | }
17 |
18 | func NewUserRepository() UserRepository {
19 | return &userRepository{}
20 | }
21 |
22 | type userRepository struct{}
23 |
24 | //登录
25 | func (n userRepository) GetUserByUserNameAndPwd(username string, password string) (user models.User) {
26 | db := datasource.GetDB()
27 | db.Where("username = ? and password = ?", username, password).First(&user)
28 | return
29 | }
30 | func (n userRepository) GetUserByUsername(username string) (user models.User) {
31 | db := datasource.GetDB()
32 | db.Where("username = ?", username).First(&user)
33 | return
34 | }
35 |
36 | //添加/修改
37 | func (n userRepository) Save(user models.User) (int, models.User) {
38 | code := 0
39 | tx := datasource.GetDB().Begin()
40 | defer utils.Defer(tx,&code)
41 | if user.ID != 0 {
42 | var oldUser models.User
43 | datasource.GetDB().First(&oldUser, user.ID)
44 | user.CreatedAt = oldUser.CreatedAt
45 | user.Username = oldUser.Username
46 | if user.Name == "" {
47 | user.Name = oldUser.Name
48 | }
49 | if user.Email == "" {
50 | user.Email = oldUser.Email
51 | }
52 | if user.Mobile == "" {
53 | user.Mobile = oldUser.Mobile
54 | }
55 | if user.QQ == "" {
56 | user.QQ = oldUser.QQ
57 | }
58 | if user.Gender == 0 {
59 | user.Gender = oldUser.Gender
60 | }
61 | if user.Age == 0 {
62 | user.Age = oldUser.Age
63 | }
64 | if user.Remark == "" {
65 | user.Remark = oldUser.Remark
66 | }
67 | }
68 | if user.Password != "" {
69 | user.Password = utils.GetMD5String(user.Password)
70 | }
71 | if err := tx.Save(&user).Error; err != nil {
72 | log.Println(err)
73 | code = -1
74 | }
75 | return code, user
76 | }
77 |
--------------------------------------------------------------------------------
/controllers/book_controller.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "../models"
5 | "../service"
6 | "log"
7 | "github.com/kataras/iris"
8 | "github.com/spf13/cast"
9 | )
10 |
11 | type BookController struct {
12 | Ctx iris.Context
13 | Service service.BookService
14 | }
15 | func NewBookController() *BookController {
16 | return &BookController{Service:service.NewBookService()}
17 | }
18 | func (g *BookController) PostList()(result models.Result) {
19 | var m map[string]interface{}
20 | err := g.Ctx.ReadJSON(&m)
21 | if err != nil {
22 | log.Println("ReadJSON Error:", err)
23 | }
24 | if m["page"] == "" || m["page"] == nil {
25 | result.Code = -1
26 | result.Msg = "参数缺失 page"
27 | return
28 | }
29 | if cast.ToUint(m["page"]) == 0 {
30 | result.Code = -1
31 | result.Msg = "参数错误 page"
32 | return
33 | }
34 | if m["size"] == "" || m["size"] == nil {
35 | result.Code = -1
36 | result.Msg = "参数缺失 size"
37 | return
38 | }
39 | if cast.ToUint(m["size"]) == 0 {
40 | result.Code = -1
41 | result.Msg = "参数错误 size"
42 | return
43 | }
44 | return g.Service.GetBookList(m)
45 | }
46 | func (g *BookController) PostSave()(result models.Result) {
47 | var book models.Book
48 | if err := g.Ctx.ReadJSON(&book); err != nil {
49 | log.Println(err)
50 | result.Msg = "数据错误"
51 | return
52 | }
53 | return g.Service.SaveBook(book)
54 | }
55 | func (g *BookController) PostGet()(result models.Result) {
56 | var m map[string]interface{}
57 | err := g.Ctx.ReadJSON(&m)
58 | if err != nil {
59 | log.Println("ReadJSON Error:", err)
60 | }
61 | if m["id"] == "" || m["id"] == nil {
62 | result.Code = -1
63 | result.Msg = "参数缺失 id"
64 | return
65 | }
66 | if cast.ToUint(m["id"]) == 0 {
67 | result.Code = -1
68 | result.Msg = "参数错误 id"
69 | return
70 | }
71 | return g.Service.GetBook(cast.ToUint(m["id"]))
72 | }
73 | func (g *BookController) PostDel()(result models.Result) {
74 | var m map[string]interface{}
75 | err := g.Ctx.ReadJSON(&m)
76 | if err != nil {
77 | log.Println("ReadJSON Error:", err)
78 | }
79 | if m["id"] == "" || m["id"] == nil {
80 | result.Code = -1
81 | result.Msg = "参数缺失 id"
82 | return
83 | }
84 | if cast.ToUint(m["id"]) == 0 {
85 | result.Code = -1
86 | result.Msg = "参数错误 id"
87 | return
88 | }
89 | return g.Service.DelBook(cast.ToUint(m["id"]))
90 | }
--------------------------------------------------------------------------------
/middleware/jwt.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "../models"
5 | "fmt"
6 | "github.com/dgrijalva/jwt-go"
7 | jwtmiddleware "github.com/iris-contrib/middleware/jwt"
8 | "github.com/kataras/iris"
9 | "github.com/spf13/cast"
10 | "log"
11 | "time"
12 | )
13 |
14 | const JwtKey = "percy"
15 |
16 | func GetJWT() *jwtmiddleware.Middleware {
17 | jwtHandler := jwtmiddleware.New(jwtmiddleware.Config{
18 | //这个方法将验证jwt的token
19 | ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
20 | //自己加密的秘钥或者说盐值
21 | return []byte(JwtKey), nil
22 | },
23 | //加密的方式
24 | SigningMethod: jwt.SigningMethodHS256,
25 | //验证未通过错误处理方式
26 | ErrorHandler: func(ctx iris.Context, s string) {
27 |
28 | fmt.Println("错误:", s)
29 | result := models.Result{Code: -1, Msg: "认证失败,请重新登录认证"}
30 | i, err := ctx.JSON(result)
31 | if err != nil {
32 | log.Println(i, err)
33 | }
34 | },
35 | })
36 | return jwtHandler
37 | }
38 |
39 | //生成token
40 | func GenerateToken(user models.User) string {
41 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
42 | "nick_name": user.Username, //用户信息
43 | "session": user.Session, //session
44 | "id": user.ID, //用户信息
45 | "iss": "Iris", //签发者
46 | "iat": time.Now().Unix(), //签发时间
47 | "jti": "9527", //jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
48 | "exp": time.Now().Add(10 * time.Hour * time.Duration(1)).Unix(), //过期时间
49 | })
50 | tokenString, _ := token.SignedString([]byte(JwtKey))
51 | fmt.Println("签发时间:", time.Now().Unix())
52 | fmt.Println("到期时间:", time.Now().Add(10 * time.Hour * time.Duration(1)).Unix())
53 | return tokenString
54 | }
55 |
56 | func ParseToken(tokenString string, key string) (interface{}, bool) {
57 | token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
58 | if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
59 | return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
60 | }
61 | return []byte(key), nil
62 | })
63 | if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
64 | return claims, true
65 | } else {
66 | fmt.Println(err)
67 | return "", false
68 | }
69 | }
70 |
71 | func GetToken(ctx iris.Context) string {
72 | token := ctx.GetHeader("Authorization")
73 | if token != "" && len(token) > 7 {
74 | token = token[7:]
75 | }
76 | return token
77 | }
78 | func GetUserID(token string) int {
79 | var userId = 0
80 | if token != "" && token != "undefined" && len(token) > 7 {
81 | v, _ := ParseToken(token, JwtKey)
82 | if v != "" {
83 | userId = cast.ToInt(v.(jwt.MapClaims)["id"])
84 | }
85 | }
86 | return userId
87 | }
88 |
--------------------------------------------------------------------------------
/db/test.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : localhost
5 | Source Server Type : MySQL
6 | Source Server Version : 50716
7 | Source Host : localhost:3306
8 | Source Schema : test
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 50716
12 | File Encoding : 65001
13 |
14 | Date: 26/12/2019 11:34:45
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for book
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `book`;
24 | CREATE TABLE `book` (
25 | `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
26 | `created_at` timestamp(0) NULL DEFAULT NULL,
27 | `updated_at` timestamp(0) NULL DEFAULT NULL,
28 | `deleted_at` timestamp(0) NULL DEFAULT NULL,
29 | `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
30 | `count` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
31 | `author` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
32 | `type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
33 | PRIMARY KEY (`id`) USING BTREE,
34 | INDEX `idx_book_deleted_at`(`deleted_at`) USING BTREE
35 | ) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
36 |
37 | -- ----------------------------
38 | -- Records of book
39 | -- ----------------------------
40 | INSERT INTO `book` VALUES (2, '2019-12-26 02:16:44', '2019-12-26 02:16:44', NULL, '红楼梦', '20', '曹雪芹', '言情');
41 | INSERT INTO `book` VALUES (3, '2019-12-26 02:18:45', '2019-12-26 02:18:45', NULL, '西游记', '12', '吴承恩', '玄幻');
42 | INSERT INTO `book` VALUES (9, '2019-12-26 02:50:40', '2019-12-26 02:50:40', NULL, '三国演义', '19', '罗贯中', '历史');
43 | INSERT INTO `book` VALUES (10, '2019-12-26 02:50:41', '2019-12-26 02:50:41', NULL, '三国演义', '19', '罗贯中', '历史');
44 | INSERT INTO `book` VALUES (11, '2019-12-26 02:50:41', '2019-12-26 02:50:41', NULL, '三国演义', '19', '罗贯中', '历史');
45 | INSERT INTO `book` VALUES (12, '2019-12-26 02:50:41', '2019-12-26 02:50:41', NULL, '三国演义', '19', '罗贯中', '历史');
46 |
47 | -- ----------------------------
48 | -- Table structure for user
49 | -- ----------------------------
50 | DROP TABLE IF EXISTS `user`;
51 | CREATE TABLE `user` (
52 | `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
53 | `created_at` timestamp(0) NULL DEFAULT NULL,
54 | `updated_at` timestamp(0) NULL DEFAULT NULL,
55 | `deleted_at` timestamp(0) NULL DEFAULT NULL,
56 | `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
57 | `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
58 | `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
59 | `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
60 | `mobile` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
61 | `qq` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
62 | `gender` int(11) NULL DEFAULT NULL,
63 | `age` int(11) NULL DEFAULT NULL,
64 | `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
65 | PRIMARY KEY (`id`) USING BTREE,
66 | UNIQUE INDEX `username`(`username`) USING BTREE,
67 | INDEX `idx_user_deleted_at`(`deleted_at`) USING BTREE
68 | ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
69 |
70 | -- ----------------------------
71 | -- Records of user
72 | -- ----------------------------
73 | INSERT INTO `user` VALUES (1, '2019-12-26 02:45:35', '2019-12-26 02:45:35', NULL, 'test', 'e10adc3949ba59abbe56e057f20f883e', '', '', '', '', 0, 0, '');
74 | INSERT INTO `user` VALUES (2, '2019-12-26 02:45:45', '2019-12-26 02:45:45', NULL, 'percy', 'e10adc3949ba59abbe56e057f20f883e', '', '', '', '', 0, 0, '');
75 |
76 | SET FOREIGN_KEY_CHECKS = 1;
77 |
--------------------------------------------------------------------------------
/db/iris-gorm-demo.postman_collection.json:
--------------------------------------------------------------------------------
1 | {
2 | "info": {
3 | "_postman_id": "7fb206d4-8547-4162-ab3a-2a369326d496",
4 | "name": "iris-gorm-demo",
5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
6 | },
7 | "item": [
8 | {
9 | "name": "登录",
10 | "request": {
11 | "auth": {
12 | "type": "bearer",
13 | "bearer": [
14 | {
15 | "key": "token",
16 | "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NjUxNzgyOTksImlhdCI6MTU2NTE0MjI5OSwiaWQiOjEsImlzcyI6IklyaXMiLCJqdGkiOiI5NTI3Iiwibmlja19uYW1lIjoicGVyY3kiLCJzZXNzaW9uIjoiIn0.HYHfYpX78GqqqwHV0PSNzJKDIyESoh-Hlvime7JigC0",
17 | "type": "string"
18 | }
19 | ]
20 | },
21 | "method": "POST",
22 | "header": [
23 | {
24 | "key": "Content-Type",
25 | "name": "Content-Type",
26 | "value": "application/json",
27 | "type": "text"
28 | }
29 | ],
30 | "body": {
31 | "mode": "raw",
32 | "raw": "{\n\t\"username\":\"test\",\n\t\"password\":\"123456\"\n}"
33 | },
34 | "url": {
35 | "raw": "localhost:8848/api/user/login",
36 | "host": [
37 | "localhost"
38 | ],
39 | "port": "8848",
40 | "path": [
41 | "api",
42 | "user",
43 | "login"
44 | ]
45 | }
46 | },
47 | "response": []
48 | },
49 | {
50 | "name": "注册",
51 | "request": {
52 | "method": "POST",
53 | "header": [
54 | {
55 | "key": "Content-Type",
56 | "name": "Content-Type",
57 | "value": "application/json",
58 | "type": "text"
59 | }
60 | ],
61 | "body": {
62 | "mode": "raw",
63 | "raw": "{\n\t\"username\":\"test\",\n\t\"password\":\"123456\"\n}",
64 | "options": {
65 | "raw": {
66 | "language": "json"
67 | }
68 | }
69 | },
70 | "url": {
71 | "raw": "localhost:8848/api/user/save",
72 | "host": [
73 | "localhost"
74 | ],
75 | "port": "8848",
76 | "path": [
77 | "api",
78 | "user",
79 | "save"
80 | ]
81 | }
82 | },
83 | "response": []
84 | },
85 | {
86 | "name": "list",
87 | "request": {
88 | "auth": {
89 | "type": "bearer",
90 | "bearer": [
91 | {
92 | "key": "token",
93 | "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzczNjM3MzEsImlhdCI6MTU3NzMyNzczMSwiaWQiOjEsImlzcyI6IklyaXMiLCJqdGkiOiI5NTI3Iiwibmlja19uYW1lIjoicGVyY3kiLCJzZXNzaW9uIjoiIn0.TjfHEIEMvYqWXWWOWU0ZELl5rJV_d0d0sGgY8Gf8g2U",
94 | "type": "string"
95 | }
96 | ]
97 | },
98 | "method": "POST",
99 | "header": [
100 | {
101 | "key": "Content-Type",
102 | "name": "Content-Type",
103 | "value": "application/json",
104 | "type": "text"
105 | }
106 | ],
107 | "body": {
108 | "mode": "raw",
109 | "raw": "{\n\t\"page\":\"1\",\n\t\"size\":\"10\"\n}",
110 | "options": {
111 | "raw": {
112 | "language": "json"
113 | }
114 | }
115 | },
116 | "url": {
117 | "raw": "localhost:8848/api/book/list",
118 | "host": [
119 | "localhost"
120 | ],
121 | "port": "8848",
122 | "path": [
123 | "api",
124 | "book",
125 | "list"
126 | ]
127 | }
128 | },
129 | "response": []
130 | },
131 | {
132 | "name": "save",
133 | "request": {
134 | "auth": {
135 | "type": "bearer",
136 | "bearer": [
137 | {
138 | "key": "token",
139 | "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzczNjM3MzEsImlhdCI6MTU3NzMyNzczMSwiaWQiOjEsImlzcyI6IklyaXMiLCJqdGkiOiI5NTI3Iiwibmlja19uYW1lIjoicGVyY3kiLCJzZXNzaW9uIjoiIn0.TjfHEIEMvYqWXWWOWU0ZELl5rJV_d0d0sGgY8Gf8g2U",
140 | "type": "string"
141 | }
142 | ]
143 | },
144 | "method": "POST",
145 | "header": [
146 | {
147 | "key": "Content-Type",
148 | "name": "Content-Type",
149 | "value": "application/json",
150 | "type": "text"
151 | }
152 | ],
153 | "body": {
154 | "mode": "raw",
155 | "raw": "{\n\n\t\"name\": \"三国演义\",\n\t\"count\": \"19\",\n\t\"author\": \"罗贯中\",\n\t\"type\":\"历史\"\n}",
156 | "options": {
157 | "raw": {
158 | "language": "json"
159 | }
160 | }
161 | },
162 | "url": {
163 | "raw": "localhost:8848/api/book/save",
164 | "host": [
165 | "localhost"
166 | ],
167 | "port": "8848",
168 | "path": [
169 | "api",
170 | "book",
171 | "save"
172 | ]
173 | }
174 | },
175 | "response": []
176 | },
177 | {
178 | "name": "del",
179 | "request": {
180 | "auth": {
181 | "type": "bearer",
182 | "bearer": [
183 | {
184 | "key": "token",
185 | "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzczNjQzNDksImlhdCI6MTU3NzMyODM0OSwiaWQiOjEsImlzcyI6IklyaXMiLCJqdGkiOiI5NTI3Iiwibmlja19uYW1lIjoidGVzdCIsInNlc3Npb24iOiIifQ.lDx-VATbskR27OIe2N2u_4nMbqC8tOXuOulZTmPPHxM",
186 | "type": "string"
187 | }
188 | ]
189 | },
190 | "method": "POST",
191 | "header": [
192 | {
193 | "key": "Content-Type",
194 | "name": "Content-Type",
195 | "value": "application/json",
196 | "type": "text"
197 | }
198 | ],
199 | "body": {
200 | "mode": "raw",
201 | "raw": "{\n\t\"id\":7\n}",
202 | "options": {
203 | "raw": {
204 | "language": "json"
205 | }
206 | }
207 | },
208 | "url": {
209 | "raw": "localhost:8848/api/book/del",
210 | "host": [
211 | "localhost"
212 | ],
213 | "port": "8848",
214 | "path": [
215 | "api",
216 | "book",
217 | "del"
218 | ]
219 | }
220 | },
221 | "response": []
222 | },
223 | {
224 | "name": "get",
225 | "request": {
226 | "auth": {
227 | "type": "bearer",
228 | "bearer": [
229 | {
230 | "key": "token",
231 | "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzczNjQzNDksImlhdCI6MTU3NzMyODM0OSwiaWQiOjEsImlzcyI6IklyaXMiLCJqdGkiOiI5NTI3Iiwibmlja19uYW1lIjoidGVzdCIsInNlc3Npb24iOiIifQ.lDx-VATbskR27OIe2N2u_4nMbqC8tOXuOulZTmPPHxM",
232 | "type": "string"
233 | }
234 | ]
235 | },
236 | "method": "POST",
237 | "header": [
238 | {
239 | "key": "Content-Type",
240 | "name": "Content-Type",
241 | "value": "application/json",
242 | "type": "text"
243 | }
244 | ],
245 | "body": {
246 | "mode": "raw",
247 | "raw": "{\n\t\"id\": \"2\"\n}",
248 | "options": {
249 | "raw": {
250 | "language": "json"
251 | }
252 | }
253 | },
254 | "url": {
255 | "raw": "localhost:8848/api/book/get",
256 | "host": [
257 | "localhost"
258 | ],
259 | "port": "8848",
260 | "path": [
261 | "api",
262 | "book",
263 | "get"
264 | ]
265 | }
266 | },
267 | "response": []
268 | }
269 | ],
270 | "protocolProfileBehavior": {}
271 | }
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
65 |
66 |
67 |
68 | ms
69 | utils
70 | fmt
71 | Status
72 | CrossAccess
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
--------------------------------------------------------------------------------