add models and jwt
This commit is contained in:
77
pkg/jwt/auth.go
Normal file
77
pkg/jwt/auth.go
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
@Time : 2020/6/29 9:05
|
||||
@Author : xuyiqing
|
||||
@File : auth.py
|
||||
*/
|
||||
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"go_blog/conf"
|
||||
"go_blog/models"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 定义jwt载荷
|
||||
type UserClaims struct {
|
||||
jwt.StandardClaims
|
||||
ID uint64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// 根据payload查询user返回
|
||||
func (c *UserClaims) GetUserByID() *models.Account {
|
||||
var user models.Account
|
||||
models.DB.Model(&models.Account{}).First(&user, c.ID)
|
||||
if user.ID > 0 {
|
||||
return &user
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// 生成jwt token字符串
|
||||
func GenToken(id uint64, username string) (string, error) {
|
||||
expiredTime := time.Now().Add(time.Hour * time.Duration(24)).Unix()
|
||||
claims := UserClaims{
|
||||
jwt.StandardClaims{
|
||||
ExpiresAt: expiredTime,
|
||||
},
|
||||
id,
|
||||
username,
|
||||
}
|
||||
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
token, err := tokenClaims.SignedString([]byte(conf.JwtSecretKey.SecretKey))
|
||||
return token, err
|
||||
}
|
||||
|
||||
// 验证token合法性
|
||||
func ValidateJwtToken(token string) (*UserClaims, error) {
|
||||
tokenClaims, err := jwt.ParseWithClaims(token, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(conf.JwtSecretKey.SecretKey), nil
|
||||
})
|
||||
|
||||
if tokenClaims != nil {
|
||||
if claims, ok := tokenClaims.Claims.(*UserClaims); ok && tokenClaims.Valid {
|
||||
return claims, nil
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 断言设定ctx的当前用户
|
||||
func AssertUser(ctx *gin.Context) *models.Account {
|
||||
currentUser, isExists := ctx.Get("CurrentUser")
|
||||
if !isExists {
|
||||
return nil
|
||||
}
|
||||
user, ok := currentUser.(*models.Account)
|
||||
if ok {
|
||||
return user
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
44
pkg/util/request.go
Normal file
44
pkg/util/request.go
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
@Time : 2020/6/29 14:40
|
||||
@Author : xuyiqing
|
||||
@File : body.py
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 反序列化request.body中的json数据为map
|
||||
func GetBodyData(ctx *gin.Context) (map[string]interface{}, error) {
|
||||
bdata := make([]byte, 1024)
|
||||
length, err := ctx.Request.Body.Read(bdata)
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
var data map[string]interface{}
|
||||
str := string(bdata[:length])
|
||||
decoder := json.NewDecoder(strings.NewReader(str))
|
||||
decoder.UseNumber()
|
||||
err1 := decoder.Decode(&data)
|
||||
if err1 != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// 构建文件url连接主机端口全链接 "https://192.168.11.121:7889/meida/upload/..."
|
||||
func BuildAbsoluteUri(ctx *gin.Context, filePath string) string {
|
||||
host := ctx.Request.Host
|
||||
schema := ctx.Request.Header.Get("X-Forwarded-Proto")
|
||||
if schema == "https" {
|
||||
return fmt.Sprintf("https://%s/%s", host, filePath)
|
||||
} else {
|
||||
return fmt.Sprintf("http://%s/%s", host, filePath)
|
||||
}
|
||||
}
|
||||
183
pkg/util/sonyflake.go
Normal file
183
pkg/util/sonyflake.go
Normal file
@@ -0,0 +1,183 @@
|
||||
// Package sonyflake implements Sonyflake, a distributed unique ID generator inspired by Twitter's Snowflake.
|
||||
//
|
||||
// A Sonyflake ID is composed of
|
||||
// 39 bits for time in units of 10 msec
|
||||
// 8 bits for a sequence number
|
||||
// 16 bits for a machine id
|
||||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// These constants are the bit lengths of Sonyflake ID parts.
|
||||
const (
|
||||
BitLenTime = 41 // bit length of time
|
||||
BitLenSequence = 10 // bit length of sequence number
|
||||
BitLenMachineID = 53 - BitLenTime - BitLenSequence // bit length of machine id
|
||||
)
|
||||
|
||||
// Settings configures Sonyflake:
|
||||
//
|
||||
// StartTime is the time since which the Sonyflake time is defined as the elapsed time.
|
||||
// If StartTime is 0, the start time of the Sonyflake is set to "2014-09-01 00:00:00 +0000 UTC".
|
||||
// If StartTime is ahead of the current time, Sonyflake is not created.
|
||||
//
|
||||
// MachineID returns the unique ID of the Sonyflake instance.
|
||||
// If MachineID returns an error, Sonyflake is not created.
|
||||
// If MachineID is nil, default MachineID is used.
|
||||
// Default MachineID returns the lower 16 bits of the private IP address.
|
||||
//
|
||||
// CheckMachineID validates the uniqueness of the machine ID.
|
||||
// If CheckMachineID returns false, Sonyflake is not created.
|
||||
// If CheckMachineID is nil, no validation is done.
|
||||
type Settings struct {
|
||||
StartTime time.Time
|
||||
MachineID func() (uint16, error)
|
||||
CheckMachineID func(uint16) bool
|
||||
}
|
||||
|
||||
// Sonyflake is a distributed unique ID generator.
|
||||
type Sonyflake struct {
|
||||
mutex *sync.Mutex
|
||||
startTime int64
|
||||
elapsedTime int64
|
||||
sequence uint16
|
||||
machineID uint16
|
||||
}
|
||||
|
||||
// NewSonyflake returns a new Sonyflake configured with the given Settings.
|
||||
// NewSonyflake returns nil in the following cases:
|
||||
// - Settings.StartTime is ahead of the current time.
|
||||
// - Settings.MachineID returns an error.
|
||||
// - Settings.CheckMachineID returns false.
|
||||
func NewSonyflake(st Settings) *Sonyflake {
|
||||
sf := new(Sonyflake)
|
||||
sf.mutex = new(sync.Mutex)
|
||||
sf.sequence = uint16(1<<BitLenSequence - 1)
|
||||
|
||||
if st.StartTime.After(time.Now()) {
|
||||
return nil
|
||||
}
|
||||
if st.StartTime.IsZero() {
|
||||
sf.startTime = toSonyflakeTime(time.Date(2014, 9, 1, 0, 0, 0, 0, time.UTC))
|
||||
} else {
|
||||
sf.startTime = toSonyflakeTime(st.StartTime)
|
||||
}
|
||||
|
||||
var err error
|
||||
if st.MachineID == nil {
|
||||
sf.machineID, err = lower16BitPrivateIP()
|
||||
} else {
|
||||
sf.machineID, err = st.MachineID()
|
||||
}
|
||||
if err != nil || (st.CheckMachineID != nil && !st.CheckMachineID(sf.machineID)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return sf
|
||||
}
|
||||
|
||||
// NextID generates a next unique ID.
|
||||
// After the Sonyflake time overflows, NextID returns an error.
|
||||
func (sf *Sonyflake) NextID() (uint64, error) {
|
||||
const maskSequence = uint16(1<<BitLenSequence - 1)
|
||||
|
||||
sf.mutex.Lock()
|
||||
defer sf.mutex.Unlock()
|
||||
|
||||
current := currentElapsedTime(sf.startTime)
|
||||
if sf.elapsedTime < current {
|
||||
sf.elapsedTime = current
|
||||
sf.sequence = 0
|
||||
} else { // sf.elapsedTime >= current
|
||||
sf.sequence = (sf.sequence + 1) & maskSequence
|
||||
if sf.sequence == 0 {
|
||||
sf.elapsedTime++
|
||||
overtime := sf.elapsedTime - current
|
||||
time.Sleep(sleepTime((overtime)))
|
||||
}
|
||||
}
|
||||
|
||||
return sf.toID()
|
||||
}
|
||||
|
||||
const sonyflakeTimeUnit = 1e7 // nsec, i.e. 10 msec
|
||||
|
||||
func toSonyflakeTime(t time.Time) int64 {
|
||||
return t.UTC().UnixNano() / sonyflakeTimeUnit
|
||||
}
|
||||
|
||||
func currentElapsedTime(startTime int64) int64 {
|
||||
return toSonyflakeTime(time.Now()) - startTime
|
||||
}
|
||||
|
||||
func sleepTime(overtime int64) time.Duration {
|
||||
return time.Duration(overtime)*10*time.Millisecond -
|
||||
time.Duration(time.Now().UTC().UnixNano()%sonyflakeTimeUnit)*time.Nanosecond
|
||||
}
|
||||
|
||||
func (sf *Sonyflake) toID() (uint64, error) {
|
||||
if sf.elapsedTime >= 1<<BitLenTime {
|
||||
return 0, errors.New("over the time limit")
|
||||
}
|
||||
|
||||
return uint64(sf.elapsedTime)<<(BitLenSequence+BitLenMachineID) |
|
||||
uint64(sf.sequence)<<BitLenMachineID |
|
||||
uint64(sf.machineID), nil
|
||||
}
|
||||
|
||||
func privateIPv4() (net.IP, error) {
|
||||
as, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, a := range as {
|
||||
ipnet, ok := a.(*net.IPNet)
|
||||
if !ok || ipnet.IP.IsLoopback() {
|
||||
continue
|
||||
}
|
||||
|
||||
ip := ipnet.IP.To4()
|
||||
if isPrivateIPv4(ip) {
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("no private ip address")
|
||||
}
|
||||
|
||||
func isPrivateIPv4(ip net.IP) bool {
|
||||
return ip != nil &&
|
||||
(ip[0] == 10 || ip[0] == 172 && (ip[1] >= 16 && ip[1] < 32) || ip[0] == 192 && ip[1] == 168)
|
||||
}
|
||||
|
||||
func lower16BitPrivateIP() (uint16, error) {
|
||||
ip, err := privateIPv4()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uint16(ip[2])<<8 + uint16(ip[3]), nil
|
||||
}
|
||||
|
||||
// Decompose returns a set of Sonyflake ID parts.
|
||||
func Decompose(id uint64) map[string]uint64 {
|
||||
const maskSequence = uint64((1<<BitLenSequence - 1) << BitLenMachineID)
|
||||
const maskMachineID = uint64(1<<BitLenMachineID - 1)
|
||||
|
||||
msb := id >> 63
|
||||
time := id >> (BitLenSequence + BitLenMachineID)
|
||||
sequence := id & maskSequence >> BitLenMachineID
|
||||
machineID := id & maskMachineID
|
||||
return map[string]uint64{
|
||||
"id": id,
|
||||
"msb": msb,
|
||||
"time": time,
|
||||
"sequence": sequence,
|
||||
"machine-id": machineID,
|
||||
}
|
||||
}
|
||||
42
pkg/util/util.go
Normal file
42
pkg/util/util.go
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
@Time : 2020/7/15 23:27
|
||||
@Author : xuyiqing
|
||||
@File : util.py
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
||||
// 判断所给路径文件/文件夹是否存在
|
||||
func FileOrDirExists(path string) bool {
|
||||
_, err := os.Stat(path) //os.Stat获取文件信息
|
||||
if err != nil {
|
||||
if os.IsExist(err) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 解决json字符串整型精度缺失
|
||||
func PrecisionLost(data interface{}) (map[string]interface{}, error) {
|
||||
bdata, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var val map[string]interface{}
|
||||
d := json.NewDecoder(bytes.NewBuffer(bdata))
|
||||
d.UseNumber()
|
||||
err = d.Decode(&val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
19
pkg/util/uuid.go
Normal file
19
pkg/util/uuid.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
var t = time.Unix(1594909810, 0)
|
||||
|
||||
var flake = NewSonyflake(Settings{
|
||||
|
||||
})
|
||||
|
||||
func GenSonyFlakeId() uint64 {
|
||||
uuid, err := flake.NextID()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
return uuid
|
||||
}
|
||||
Reference in New Issue
Block a user