[ADD]登陆验证

This commit is contained in:
viletyy 2019-08-12 21:05:20 +08:00
parent ef49bdf01b
commit 1ca77573bc
16 changed files with 562 additions and 26 deletions

View File

@ -1,7 +0,0 @@
package api
import "github.com/gin-gonic/gin"
func GetAuth(c *gin.Context) {
}

View File

@ -16,6 +16,7 @@ import (
// @Description // @Description
// @Accept json // @Accept json
// @Produce json // @Produce json
// @Param Authorization header string true "auth by /auth"
// @Success 200 {string} json "{"code" : 200, "data" : {}, "msg" : "ok"}" // @Success 200 {string} json "{"code" : 200, "data" : {}, "msg" : "ok"}"
// @Router /v1/businesses [get] // @Router /v1/businesses [get]
func GetBusinesses(c *gin.Context) { func GetBusinesses(c *gin.Context) {

View File

@ -36,7 +36,7 @@ func GetMetaDatabases(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"code": code, "code": code,
"msg": e.GetMsg(code), "msg": e.GetMsg(code),
"basic": data, "data": data,
}) })
} }

141
controller/api/v1/user.go Normal file
View File

@ -0,0 +1,141 @@
package v1
import (
"github.com/astaxie/beego/validation"
"github.com/gin-gonic/gin"
"github.com/viletyy/potato/models"
"github.com/viletyy/potato/pkg/e"
"github.com/viletyy/potato/pkg/logging"
"github.com/viletyy/potato/pkg/setting"
"github.com/viletyy/potato/pkg/util"
"net/http"
)
type user struct {
Username string `valid:"Required; MaxSize(50)"`
Password string `valid:"Required; MaxSize(50)"`
}
// @Summary 用户验证
// @Description
// @Accept json
// @Produce json
// @Param username query string true "用户 用户名"
// @Param password query string true "用户 密码"
// @Success 200 {string} json "{"code" : 200, "data" : {"token" : ""}, "msg" : "ok"}"
// @Router /v1/auth [get]
func GetUserAuth(c *gin.Context) {
username := c.Query("username")
password := c.Query("password")
valid := validation.Validation{}
a := user{Username: username, Password: password}
ok, err := valid.Valid(&a)
logging.Info(err)
data := make(map[string]interface{})
code := e.INVALID_PARAMS
if ok {
isExist := models.CheckUser(username, password)
if isExist {
token, err := util.GenerateToken(username, password)
if err != nil {
code = e.ERROR_AUTH_TOKEN
} else {
data["token"] = token
code = e.SUCCESS
}
} else {
code = e.ERROR_AUTH
}
} else {
for _, err := range valid.Errors {
logging.Info(err.Key, err.Message)
}
}
c.JSON(http.StatusOK, gin.H{
"code" : code,
"msg" : e.GetMsg(code),
"data" : data,
})
}
// @Summary 用户列表
// @Tags users
// @Description
// @Accept json
// @Produce json
// @Success 200 {string} json "{"code" : 200, "data" : {}, "msg" : "ok"}"
// @Router /v1/users [get]
func GetUsers(c *gin.Context) {
username := c.Query("username")
nickname := c.Query("nickname")
maps := make(map[string]interface{})
data := make(map[string]interface{})
if username != "" {
maps["username"] = username
}
if nickname != "" {
maps["nickname"] = nickname
}
data["lists"] = models.GetUsers(util.GetPage(c), setting.PageSize, maps)
data["total"] = models.GetUsersTotal(maps)
code := e.SUCCESS
c.JSON(http.StatusOK, gin.H{
"code" : code,
"msg" : e.GetMsg(code),
"data" : data,
})
}
// @Summary 新增用户
// @Tags users
// @Description
// @Accept mpfd
// @Produce json
// @Param username formData string true "用户 用户名"
// @Param password formData string true "用户 密码"
// @Param nickname formData string true "用户 真实姓名"
// @Success 200 {string} json "{"code" : 200, data: {}, "msg" : "ok"}"
// @Router /v1/users [post]
func AddUser(c *gin.Context) {
username := c.PostForm("username")
password := c.PostForm("password")
nickname := c.PostForm("nickname")
valid := validation.Validation{}
valid.Required(username, "username").Message("用户名不能为空")
valid.Required(password, "password").Message("密码不能为空")
valid.Required(nickname, "password").Message("真实姓名不能为空")
data := make(map[string]interface{})
code := e.INVALID_PARAMS
if ! valid.HasErrors() {
if ! models.ExistUserByUsername(username) {
data["Username"] = username
data["Password"] = models.GetSecretPassword(password)
data["Nickname"] = nickname
code = e.SUCCESS
} else {
code = e.ERROR_EXIST_USER
}
}
if code == 200 {
models.AddUser(data)
}
c.JSON(http.StatusOK, gin.H{
"code" : code,
"msg" : e.GetMsg(code),
"data" : data,
})
}

View File

@ -1,6 +1,6 @@
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag at // This file was generated by swaggo/swag at
// 2019-08-12 01:35:45.643682 +0800 CST m=+0.068783392 // 2019-08-12 20:14:10.089932 +0800 CST m=+0.057625886
package docs package docs
@ -26,6 +26,41 @@ var doc = `{
"host": "{{.Host}}", "host": "{{.Host}}",
"basePath": "{{.BasePath}}", "basePath": "{{.BasePath}}",
"paths": { "paths": {
"/v1/auth": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"summary": "用户验证",
"parameters": [
{
"type": "string",
"description": "用户 用户名",
"name": "username",
"in": "query",
"required": true
},
{
"type": "string",
"description": "用户 密码",
"name": "password",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "{\"code\" : 200, \"data\" : {\"token\" : \"\"}, \"msg\" : \"ok\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/v1/businesses": { "/v1/businesses": {
"get": { "get": {
"consumes": [ "consumes": [
@ -38,6 +73,15 @@ var doc = `{
"businesses" "businesses"
], ],
"summary": "业务系统列表", "summary": "业务系统列表",
"parameters": [
{
"type": "string",
"description": "auth by /auth",
"name": "Authorization",
"in": "header",
"required": true
}
],
"responses": { "responses": {
"200": { "200": {
"description": "{\"code\" : 200, \"data\" : {}, \"msg\" : \"ok\"}", "description": "{\"code\" : 200, \"data\" : {}, \"msg\" : \"ok\"}",
@ -418,6 +462,71 @@ var doc = `{
} }
} }
}, },
"/v1/users": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "用户列表",
"responses": {
"200": {
"description": "{\"code\" : 200, \"data\" : {}, \"msg\" : \"ok\"}",
"schema": {
"type": "string"
}
}
}
},
"post": {
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "新增用户",
"parameters": [
{
"type": "string",
"description": "用户 用户名",
"name": "username",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "用户 密码",
"name": "password",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "用户 真实姓名",
"name": "nickname",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "{\"code\" : 200, data: {}, \"msg\" : \"ok\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/v1/vendors": { "/v1/vendors": {
"get": { "get": {
"consumes": [ "consumes": [

View File

@ -9,6 +9,41 @@
}, },
"basePath": "/api", "basePath": "/api",
"paths": { "paths": {
"/v1/auth": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"summary": "用户验证",
"parameters": [
{
"type": "string",
"description": "用户 用户名",
"name": "username",
"in": "query",
"required": true
},
{
"type": "string",
"description": "用户 密码",
"name": "password",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "{\"code\" : 200, \"data\" : {\"token\" : \"\"}, \"msg\" : \"ok\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/v1/businesses": { "/v1/businesses": {
"get": { "get": {
"consumes": [ "consumes": [
@ -21,6 +56,15 @@
"businesses" "businesses"
], ],
"summary": "业务系统列表", "summary": "业务系统列表",
"parameters": [
{
"type": "string",
"description": "auth by /auth",
"name": "Authorization",
"in": "header",
"required": true
}
],
"responses": { "responses": {
"200": { "200": {
"description": "{\"code\" : 200, \"data\" : {}, \"msg\" : \"ok\"}", "description": "{\"code\" : 200, \"data\" : {}, \"msg\" : \"ok\"}",
@ -401,6 +445,71 @@
} }
} }
}, },
"/v1/users": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "用户列表",
"responses": {
"200": {
"description": "{\"code\" : 200, \"data\" : {}, \"msg\" : \"ok\"}",
"schema": {
"type": "string"
}
}
}
},
"post": {
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "新增用户",
"parameters": [
{
"type": "string",
"description": "用户 用户名",
"name": "username",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "用户 密码",
"name": "password",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "用户 真实姓名",
"name": "nickname",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "{\"code\" : 200, data: {}, \"msg\" : \"ok\"}",
"schema": {
"type": "string"
}
}
}
}
},
"/v1/vendors": { "/v1/vendors": {
"get": { "get": {
"consumes": [ "consumes": [

View File

@ -6,10 +6,39 @@ info:
title: Potato Api title: Potato Api
version: "1.0" version: "1.0"
paths: paths:
/v1/auth:
get:
consumes:
- application/json
parameters:
- description: 用户 用户名
in: query
name: username
required: true
type: string
- description: 用户 密码
in: query
name: password
required: true
type: string
produces:
- application/json
responses:
"200":
description: '{"code" : 200, "data" : {"token" : ""}, "msg" : "ok"}'
schema:
type: string
summary: 用户验证
/v1/businesses: /v1/businesses:
get: get:
consumes: consumes:
- application/json - application/json
parameters:
- description: auth by /auth
in: header
name: Authorization
required: true
type: string
produces: produces:
- application/json - application/json
responses: responses:
@ -265,6 +294,49 @@ paths:
summary: 元数据列表 summary: 元数据列表
tags: tags:
- meta_tables - meta_tables
/v1/users:
get:
consumes:
- application/json
produces:
- application/json
responses:
"200":
description: '{"code" : 200, "data" : {}, "msg" : "ok"}'
schema:
type: string
summary: 用户列表
tags:
- users
post:
consumes:
- multipart/form-data
parameters:
- description: 用户 用户名
in: formData
name: username
required: true
type: string
- description: 用户 密码
in: formData
name: password
required: true
type: string
- description: 用户 真实姓名
in: formData
name: nickname
required: true
type: string
produces:
- application/json
responses:
"200":
description: '{"code" : 200, data: {}, "msg" : "ok"}'
schema:
type: string
summary: 新增用户
tags:
- users
/v1/vendors: /v1/vendors:
get: get:
consumes: consumes:

View File

@ -1,9 +1,9 @@
package jwt package jwt
import ( import (
"game_demo/pkg/e"
"game_demo/pkg/util"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/viletyy/potato/pkg/e"
"github.com/viletyy/potato/pkg/util"
"net/http" "net/http"
"time" "time"
) )
@ -24,13 +24,19 @@ func JWT() gin.HandlerFunc {
} else if time.Now().Unix() > claims.ExpiresAt { } else if time.Now().Unix() > claims.ExpiresAt {
code = e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT code = e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT
} }
username := claims.Username
loginUUID := claims.StandardClaims.Id
val, err := util.Redis.Get("login:" + loginUUID).Result()
if val != username {
code = e.ERROR_AUTH_CHECK_TOKEN_FAIL
}
} }
if code != e.SUCCESS { if code != e.SUCCESS {
c.JSON(http.StatusUnauthorized, gin.H{ c.JSON(http.StatusUnauthorized, gin.H{
"code" : code, "code" : code,
"msg" : e.GetMsg(code), "msg" : e.GetMsg(code),
"basic" : data, "data" : data,
}) })
c.Abort() c.Abort()

View File

@ -1,7 +0,0 @@
package basic
import "github.com/viletyy/potato/pkg/util"
func init() {
util.DB.AutoMigrate(&MetaDatabase{}, &Vendor{}, &Business{})
}

10
models/migrate.go Normal file
View File

@ -0,0 +1,10 @@
package models
import (
"github.com/viletyy/potato/models/basic"
"github.com/viletyy/potato/pkg/util"
)
func init() {
util.DB.AutoMigrate(&User{}, &basic.MetaDatabase{}, &basic.Vendor{}, &basic.Business{})
}

84
models/user.go Normal file
View File

@ -0,0 +1,84 @@
package models
import (
"crypto/md5"
"fmt"
"github.com/viletyy/potato/pkg/util"
"io"
"log"
)
type User struct {
util.Model
Username string `json:"username"`
Password string `json:"password"`
Nickname string `json:"nickname"`
}
func CheckUser(username, password string) bool {
var user User
util.DB.Select("id").Where(User{Username: username, Password: GetSecretPassword(password)}).First(&user)
if user.ID > 0 {
return true
}
return false
}
func GetSecretPassword(password string) string {
h := md5.New()
io.WriteString(h, password)
final := fmt.Sprintf("%x", h.Sum(nil))
return final
}
func GetUsers(pageNum int, pageSize int, maps interface{}) (users []User) {
util.DB.Where(maps).Offset(pageNum).Limit(pageSize).Find(&users)
return
}
func GetUsersTotal(maps interface{}) (count int) {
util.DB.Model(&User{}).Where(maps).Count(&count)
return
}
func ExistUserByUsername(username string) bool {
var user User
util.DB.Select("id").Where("name = ?", username).First(&user)
if user.ID > 0 {
return true
}
return false
}
func ExistUserById(id int) bool {
var user User
util.DB.Select("id").Where("id = ?", id).First(&user)
if user.ID > 0 {
return true
}
return false
}
func AddUser(data map[string]interface{}) bool {
user := &User{}
error := util.FillStruct(data, user)
if error != nil {
log.Printf("Fill Struct is Fail")
}
util.DB.Create(user)
return true
}
func EditUser(id int, data interface{}) bool {
util.DB.Model(&User{}).Where("id = ?", id).Update(data)
return true
}
func DeleteUser(id int) bool {
util.DB.Where("id = ?", id).Delete(&User{})
return true
}

View File

@ -5,6 +5,8 @@ const (
ERROR = 500 ERROR = 500
INVALID_PARAMS = 400 INVALID_PARAMS = 400
ERROR_EXIST_USER = 10001
ERROR_NOT_EXIST_USER = 10002
ERROR_EXIST_VENDOR = 10011 ERROR_EXIST_VENDOR = 10011
ERROR_NOT_EXIST_VENDOR = 10012 ERROR_NOT_EXIST_VENDOR = 10012
ERROR_EXIST_BUSINESS = 10021 ERROR_EXIST_BUSINESS = 10021

View File

@ -4,6 +4,9 @@ var MsgFlags = map[int]string {
SUCCESS : "ok", SUCCESS : "ok",
ERROR : "fail", ERROR : "fail",
INVALID_PARAMS : "请求参数错误", INVALID_PARAMS : "请求参数错误",
ERROR_EXIST_USER : "已存在该用户",
ERROR_NOT_EXIST_USER : "该用户不存在",
ERROR_EXIST_VENDOR : "已存在该系统厂商", ERROR_EXIST_VENDOR : "已存在该系统厂商",
ERROR_NOT_EXIST_VENDOR : "该系统厂商不存在", ERROR_NOT_EXIST_VENDOR : "该系统厂商不存在",
ERROR_EXIST_BUSINESS : "已存在该业务系统", ERROR_EXIST_BUSINESS : "已存在该业务系统",

View File

@ -32,7 +32,7 @@ func init() {
InitDB() InitDB()
//defer DB.Close() //defer DB.Close()
InitRedis() InitRedis()
defer Redis.Close() //defer Redis.Close()
} }
func InitDB() *gorm.DB { func InitDB() *gorm.DB {
@ -75,7 +75,7 @@ func InitDB() *gorm.DB {
return DB return DB
} }
func InitRedis() { func InitRedis() *redis.Client {
sec, err := setting.Cfg.GetSection("redis") sec, err := setting.Cfg.GetSection("redis")
if err != nil { if err != nil {
@ -89,9 +89,11 @@ func InitRedis() {
), ),
}) })
if _, err := Redis.Ping().Result(); err != nil { _, err = Redis.Ping().Result()
if err != nil {
logging.Fatal("redis连接失败!", err) logging.Fatal("redis连接失败!", err)
} }
return Redis
} }
func FillStruct(data map[string]interface{}, obj interface{}) error { func FillStruct(data map[string]interface{}, obj interface{}) error {

View File

@ -1,7 +1,9 @@
package util package util
import ( import (
"fmt"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/google/uuid"
"github.com/viletyy/potato/pkg/setting" "github.com/viletyy/potato/pkg/setting"
"time" "time"
) )
@ -16,19 +18,23 @@ type Claims struct {
func GenerateToken(username, password string) (string, error) { func GenerateToken(username, password string) (string, error) {
nowTime := time.Now() nowTime := time.Now()
expireTime := nowTime.Add(3 * time.Hour) expireTime := nowTime.Add(time.Minute * 30)
loginUUID := uuid.New().String()
claims := Claims{ claims := Claims{
Username: username, Username: username,
Password: password, Password: password,
StandardClaims: jwt.StandardClaims{ StandardClaims: jwt.StandardClaims{
ExpiresAt: expireTime.Unix(), ExpiresAt: expireTime.Unix(),
Issuer : "gin-game-demo", Issuer : "data_govern",
Id : loginUUID,
}, },
} }
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
token, err := tokenClaims.SignedString(jwtSecret) token, err := tokenClaims.SignedString(jwtSecret)
result, err := Redis.Set("login:" + loginUUID, username, 1*time.Hour).Result()
fmt.Println(result, err)
return token, err return token, err
} }

View File

@ -6,9 +6,10 @@ import (
ginSwagger "github.com/swaggo/gin-swagger" ginSwagger "github.com/swaggo/gin-swagger"
"github.com/swaggo/gin-swagger/swaggerFiles" "github.com/swaggo/gin-swagger/swaggerFiles"
_ "github.com/swaggo/gin-swagger/swaggerFiles" _ "github.com/swaggo/gin-swagger/swaggerFiles"
"github.com/viletyy/potato/controller/api" v1 "github.com/viletyy/potato/controller/api/v1"
_ "github.com/viletyy/potato/docs" _ "github.com/viletyy/potato/docs"
"github.com/viletyy/potato/middleware/cors" "github.com/viletyy/potato/middleware/cors"
"github.com/viletyy/potato/middleware/jwt"
"github.com/viletyy/potato/pkg/setting" "github.com/viletyy/potato/pkg/setting"
) )
@ -26,7 +27,7 @@ func InitRouter() *gin.Engine {
Engine.Use(cors.CORSMiddleware()) Engine.Use(cors.CORSMiddleware())
Engine.GET("/auth", api.GetAuth) Engine.GET("/api/v1/auth", v1.GetUserAuth)
Engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) Engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
V1InitModule() V1InitModule()
@ -35,5 +36,9 @@ func InitRouter() *gin.Engine {
} }
func V1InitModule() { func V1InitModule() {
V1RouterGroup.Use(jwt.JWT())
users := V1RouterGroup.Group("users")
users.GET("", v1.GetUsers)
users.POST("", v1.AddUser)
V1InitBasicRouter() V1InitBasicRouter()
} }