细节调整

This commit is contained in:
TianJun 2021-04-29 18:45:54 +08:00
parent f80831d013
commit 343bd3f137
12 changed files with 294 additions and 153 deletions

1
go.mod
View File

@ -14,6 +14,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.7 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
github.com/satori/go.uuid v1.2.0
github.com/sirupsen/logrus v1.8.1
golang.org/x/sys v0.0.0-20210112080510-489259a85091 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect

2
go.sum
View File

@ -76,6 +76,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

View File

@ -1,6 +1,6 @@
package base
type SimplePageData struct {
total uint `json:"total"`
data interface{} `json:"data"`
Total int `json:"total"`
Data interface{} `json:"data"`
}

View File

@ -3,11 +3,15 @@ package main
import (
"lingye-gin/src/config"
"lingye-gin/src/middleware"
v1 "lingye-gin/src/test/v1"
)
func main() {
// 初始化yaml配置
new(config.ApplicationProperties).Init()
v1.DescribeStudents(nil)
// 初始化redis
new(middleware.RedisPool).Init()
// 初始化gorm, 注册表

View File

@ -6,7 +6,6 @@ import (
"lingye-gin/src/modules/system/service/dto"
"lingye-gin/src/modules/system/service/query"
"lingye-gin/src/util"
"net/http"
)
// 统一Service对象
@ -15,30 +14,18 @@ var userService = &service.UserService{}
func DescribeUsers(c *gin.Context) {
var userQuery query.UserQuery
_ = c.BindJSON(&userQuery)
users, total := userService.DescribeUsers(userQuery)
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"data": users,
"total": total,
})
util.RSuccessJson(c, util.BuildPageData(users, total))
}
func DescribeUserById(c *gin.Context) {
id := c.Params.ByName("id")
user := userService.DescribeUserById(util.StringToUInt64(id))
if user.ID == 0 {
c.JSON(http.StatusNotFound, gin.H{
"code": http.StatusNotFound,
"message": "user not found",
})
util.RErrorMsg(c, "该用户信息未查询到")
return
}
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"message": "success",
"data": user,
})
util.RSuccessJson(c, user)
}
func CreateUser(c *gin.Context) {
@ -46,29 +33,20 @@ func CreateUser(c *gin.Context) {
// 绑定一个请求主体到一个类型
_ = c.BindJSON(&userDTO)
userService.Save(&userDTO)
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"message": "success",
})
util.RSuccessMsg(c, "创建成功!")
}
func ModifyUserById(c *gin.Context) {
id := c.Params.ByName("id")
localUser := userService.DescribeUserById(util.StringToUInt64(id))
if localUser.ID == 0 {
c.JSON(http.StatusNotFound, gin.H{
"code": http.StatusNotFound,
"message": "user not found",
})
util.RErrorMsg(c, "非法操作, 该用户信息未查询到!")
return
} else {
var userDTO dto.UserDTO
_ = c.BindJSON(&userDTO)
userService.ModifyById(&userDTO)
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"message": "success",
})
util.RSuccessMsg(c, "修改成功!")
}
}
@ -77,16 +55,10 @@ func DeleteUserById(c *gin.Context) {
uid := util.StringToUInt64(id)
localUser := userService.DescribeUserById(uid)
if localUser.ID == 0 {
c.JSON(http.StatusNotFound, gin.H{
"code": http.StatusNotFound,
"message": "user not found",
})
util.RErrorMsg(c, "非法操作, 该用户信息未查询到!")
return
} else {
userService.RemoveById(uid)
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"message": "success",
})
util.RSuccessMsg(c, "删除成功!")
}
}

View File

@ -17,5 +17,5 @@ func DescribeSign(c *gin.Context) {
}
res["sn"] = util.CreateSign(params)
res["ts"] = ts
util.RetJson("200", "", res, c)
util.RSuccessJson(c, res)
}

View File

@ -3,6 +3,8 @@ package v1
import (
"fmt"
"github.com/gin-gonic/gin"
"lingye-gin/src/base"
"lingye-gin/src/util"
)
type Student struct {
@ -13,11 +15,11 @@ type Student struct {
func DescribeStudents(c *gin.Context) {
var students []Student
c.JSON(200, gin.H{
"data": students,
"page": 1,
"pageSize": 15,
})
var pageData base.SimplePageData
pageData.Total = 0
pageData.Data = students
util.RSuccessWithMsgJson(c, "分页获取学生列表成功!", pageData)
}
func DescribeStudentById(c *gin.Context) {
@ -25,17 +27,17 @@ func DescribeStudentById(c *gin.Context) {
fmt.Println("id=", id)
var student Student
if student.ID == 0 {
c.JSON(404, gin.H{"message": "student not found"})
util.RErrorJson(c, "没有找到该学生信息", nil)
return
}
c.JSON(200, student)
util.RSuccessJson(c, student)
}
func CreateStudent(c *gin.Context) {
var student Student
// 绑定一个请求主体到一个类型
_ = c.BindJSON(&student)
c.JSON(200, "创建成功")
util.RSuccessWithMsgJson(c, "创建成功", nil)
}
func ModifyStudentById(c *gin.Context) {
@ -43,11 +45,11 @@ func ModifyStudentById(c *gin.Context) {
fmt.Println("id=", id)
var student Student
if student.ID == 0 {
c.JSON(404, gin.H{"message": "student not found"})
util.RErrorJson(c, "非法操作, 没有找到该学生信息!", nil)
return
} else {
_ = c.BindJSON(&student)
c.JSON(200, student)
util.RSuccessJson(c, student)
}
}
@ -56,10 +58,10 @@ func DeleteStudentById(c *gin.Context) {
fmt.Println("id=", id)
var student Student
if student.ID == 0 {
c.JSON(404, gin.H{"message": "student not found"})
util.RErrorJson(c, "非法操作, 没有找到该学生信息!", nil)
return
} else {
_ = c.BindJSON(&student)
c.JSON(200, gin.H{"message": "delete success"})
util.RSuccessMsg(c, "删除成功")
}
}

View File

@ -2,6 +2,8 @@ package v2
import (
"github.com/gin-gonic/gin"
"lingye-gin/src/base"
"lingye-gin/src/util"
)
type Student struct {
@ -12,9 +14,9 @@ type Student struct {
func DescribeStudents(c *gin.Context) {
var students []Student
c.JSON(200, gin.H{
"data": students,
"page": 1,
"pageSize": 15,
})
var pageData base.SimplePageData
pageData.Total = 0
pageData.Data = students
util.RSuccessWithMsgJson(c, "分页获取学生列表成功!", pageData)
}

113
src/util/aes_utils.go Normal file
View File

@ -0,0 +1,113 @@
package util
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"errors"
"fmt"
"github.com/satori/go.uuid"
"lingye-gin/src/config"
"strings"
)
// 高级加密标准Advanced Encryption Standard, AES
type AESUtils struct{}
// 16,24,32位字符串的话, 分别对应AES-128, AES-192, AES-256 加密方法
// key不能泄露
func (AESUtils) GetRandomPwdKey() string {
u2 := uuid.NewV4()
return strings.Replace(u2.String(), "-", "", -1)
}
// PKCS7 填充模式
func (AESUtils) PKCS7Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
// Repeat()函数的功能是把切片[]byte{byte(padding)}复制padding个, 然后合并成新的字节切片返回
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padText...)
}
// 填充的反向操作, 删除填充字符串
func (AESUtils) PKCS7UnPadding(origData []byte) ([]byte, error) {
// 获取数据长度
length := len(origData)
if length == 0 {
return nil, errors.New("加密字符串错误!")
} else {
// 获取填充字符串长度
unPadding := int(origData[length-1])
// 截取切片, 删除填充字节, 并且返回明文
return origData[:(length - unPadding)], nil
}
}
// 实现加密
func (util AESUtils) AesEncrypt(origData []byte, key []byte) ([]byte, error) {
// 创建加密算法实例
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// 获取块的大小
blockSize := block.BlockSize()
// 对数据进行填充,让数据长度满足需求
origData = util.PKCS7Padding(origData, blockSize)
// 采用AES加密方法中CBC加密模式
blocMode := cipher.NewCBCEncrypter(block, key[:blockSize])
result := make([]byte, len(origData))
// 执行加密
blocMode.CryptBlocks(result, origData)
return result, nil
}
// 实现解密
func (util AESUtils) AesDeCrypt(cypted []byte, key []byte) ([]byte, error) {
// 创建加密算法实例
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// 获取块大小
blockSize := block.BlockSize()
// 创建加密客户端实例
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
origData := make([]byte, len(cypted))
// 这个函数也可以用来解密
blockMode.CryptBlocks(origData, cypted)
// 去除填充字符串
origData, err = util.PKCS7UnPadding(origData)
if err != nil {
return nil, err
}
return origData, err
}
// 加密base64
func (util AESUtils) EnPwdCode(pwd []byte) (string, error) {
result, err := util.AesEncrypt(pwd, []byte(config.AppProps.Jwt.Secret))
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(result), err
}
// 解密
func (util AESUtils) DePwdCode(pwd string) ([]byte, error) {
// 解密base64字符串
pwdByte, err := base64.StdEncoding.DecodeString(pwd)
if err != nil {
return nil, err
}
// 执行AES解密
return util.AesDeCrypt(pwdByte, []byte(config.AppProps.Jwt.Secret))
}
func (util AESUtils) Test() {
str := []byte("加密测试")
pwd, _ := util.EnPwdCode(str)
bt, _ := util.DePwdCode(pwd)
fmt.Println(string(bt))
}

49
src/util/http_utils.go Normal file
View File

@ -0,0 +1,49 @@
package util
import (
"github.com/gin-gonic/gin"
"net/http"
)
func RErrorJson(c *gin.Context, msg string, data interface{}) {
c.JSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": msg,
"data": data,
})
c.Abort()
}
func RSuccessJson(c *gin.Context, data interface{}) {
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"msg": "success",
"data": data,
})
c.Abort()
}
func RSuccessMsg(c *gin.Context, msg string) {
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"msg": "success",
})
c.Abort()
}
func RErrorMsg(c *gin.Context, msg string) {
c.JSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": "success",
})
c.Abort()
}
func RSuccessWithMsgJson(c *gin.Context, msg string, data interface{}) {
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"msg": msg,
"data": data,
})
c.Abort()
}

84
src/util/sign_utils.go Normal file
View File

@ -0,0 +1,84 @@
package util
import (
"crypto/md5"
"encoding/hex"
"fmt"
"github.com/gin-gonic/gin"
"lingye-gin/src/config"
"net/url"
"sort"
"strconv"
"time"
)
// MD5 方法
func MD5(str string) string {
s := md5.New()
s.Write([]byte(str))
return hex.EncodeToString(s.Sum(nil))
}
// 获取当前时间戳
func GetTimeUnix() int64 {
return time.Now().Unix()
}
// 生成签名
func CreateSign(params url.Values) string {
var key []string
var str = ""
for k := range params {
if k != "sn" {
key = append(key, k)
}
}
sort.Strings(key)
for i := 0; i < len(key); i++ {
if i == 0 {
str = fmt.Sprintf("%v=%v", key[i], params.Get(key[i]))
} else {
str = str + fmt.Sprintf("&%v=%v", key[i], params.Get(key[i]))
}
}
// 自定义签名算法
sign := MD5(MD5(str) + MD5(config.AppProps.App.Name+config.AppProps.Jwt.Secret))
return sign
}
// 验证签名
func VerifySign(c *gin.Context) {
var method = c.Request.Method
var ts int64
var sn string
var req url.Values
if method == "GET" {
req = c.Request.URL.Query()
sn = c.Query("sn")
ts, _ = strconv.ParseInt(c.Query("ts"), 10, 64)
} else if method == "POST" {
_ = c.Request.ParseForm()
req = c.Request.PostForm
sn = c.PostForm("sn")
ts, _ = strconv.ParseInt(c.PostForm("ts"), 10, 64)
} else {
RErrorJson(c, "Illegal requests", "")
return
}
exp, _ := strconv.ParseInt(string(rune(config.AppProps.Jwt.Expiry)), 10, 64)
// 验证过期时间
if ts > GetTimeUnix() || GetTimeUnix()-ts >= exp {
RErrorJson(c, "Ts Error", "")
return
}
// 验证签名
if sn == "" || sn != CreateSign(req) {
RErrorJson(c, "Sn Error", "")
return
}
}

View File

@ -1,48 +1,11 @@
package util
import (
"crypto/md5"
"encoding/hex"
"fmt"
"github.com/gin-gonic/gin"
"lingye-gin/src/config"
"net/http"
"net/url"
"lingye-gin/src/base"
"reflect"
"sort"
"strconv"
"time"
)
// 打印
func Print(i interface{}) {
fmt.Println("---")
fmt.Println(i)
fmt.Println("---")
}
// 返回JSON
func RetJson(code, msg string, data interface{}, c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"code": code,
"msg": msg,
"data": data,
})
c.Abort()
}
// 获取当前时间戳
func GetTimeUnix() int64 {
return time.Now().Unix()
}
// MD5 方法
func MD5(str string) string {
s := md5.New()
s.Write([]byte(str))
return hex.EncodeToString(s.Sum(nil))
}
// 修正分页参数
func FixPage(page uint, pageSize uint) (p uint, ps uint) {
if page == 0 {
@ -54,65 +17,6 @@ func FixPage(page uint, pageSize uint) (p uint, ps uint) {
return p, ps
}
// 生成签名
func CreateSign(params url.Values) string {
var key []string
var str = ""
for k := range params {
if k != "sn" {
key = append(key, k)
}
}
sort.Strings(key)
for i := 0; i < len(key); i++ {
if i == 0 {
str = fmt.Sprintf("%v=%v", key[i], params.Get(key[i]))
} else {
str = str + fmt.Sprintf("&%v=%v", key[i], params.Get(key[i]))
}
}
// 自定义签名算法
sign := MD5(MD5(str) + MD5(config.AppProps.App.Name+config.AppProps.Jwt.Secret))
return sign
}
// 验证签名
func VerifySign(c *gin.Context) {
var method = c.Request.Method
var ts int64
var sn string
var req url.Values
if method == "GET" {
req = c.Request.URL.Query()
sn = c.Query("sn")
ts, _ = strconv.ParseInt(c.Query("ts"), 10, 64)
} else if method == "POST" {
_ = c.Request.ParseForm()
req = c.Request.PostForm
sn = c.PostForm("sn")
ts, _ = strconv.ParseInt(c.PostForm("ts"), 10, 64)
} else {
RetJson("500", "Illegal requests", "", c)
return
}
exp, _ := strconv.ParseInt(string(rune(config.AppProps.Jwt.Expiry)), 10, 64)
// 验证过期时间
if ts > GetTimeUnix() || GetTimeUnix()-ts >= exp {
RetJson("500", "Ts Error", "", c)
return
}
// 验证签名
if sn == "" || sn != CreateSign(req) {
RetJson("500", "Sn Error", "", c)
return
}
}
// source 有数据的结构体
// target 空的结构体
func StructCopy(source interface{}, target interface{}) {
@ -133,3 +37,11 @@ func StringToUInt64(number string) uint64 {
result, _ := strconv.Atoi(number)
return uint64(result)
}
// 构成分页对象
func BuildPageData(data interface{}, total int) base.SimplePageData {
var pageData base.SimplePageData
pageData.Data = data
pageData.Total = total
return pageData
}