first commit

This commit is contained in:
JiXieShi
2024-11-14 22:55:43 +08:00
commit 421cfb8cfa
98 changed files with 12617 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
package middleware
import (
"licserver/internal/utils"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
func JWTAuth(config *utils.JWTConfig) gin.HandlerFunc {
return func(c *gin.Context) {
var token string
// 1. 首先从 cookie 中获取 token
tokenCookie, err := c.Cookie("token")
if err == nil {
token = tokenCookie
}
// 2. 如果 cookie 中没有,则从 header 中获取
if token == "" {
auth := c.GetHeader("Authorization")
if auth != "" {
parts := strings.SplitN(auth, " ", 2)
if len(parts) == 2 && parts[0] == "Bearer" {
token = parts[1]
}
}
}
// 3. 如果 query 参数中有 token也可以使用
if token == "" {
token = c.Query("token")
}
// 如果都没有找到 token
if token == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "未提供认证信息"})
c.Abort()
return
}
// 验证 token
claims, err := utils.ParseToken(token, config)
if err != nil {
// 如果 token 无效,清除 cookie
// c.SetCookie("token", "", -1, "/", "", true, true)
c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的token"})
c.Abort()
return
}
// 将用户信息存储到上下文
c.Set("userID", claims.UserID)
c.Set("username", claims.Username)
c.Set("role", claims.Role)
// 如果是从 header 或 query 参数获取的 token设置到 cookie 中
if tokenCookie == "" {
// 设置 cookie过期时间与 token 一致
// c.SetCookie("token", token, int(claims.ExpiresAt.Unix()-claims.IssuedAt.Unix()), "/", "", false, true)
}
c.Next()
}
}
// AdminRequired 检查用户是否为管理员
func AdminRequired() gin.HandlerFunc {
return func(c *gin.Context) {
role, exists := c.Get("role")
if !exists || role != "admin" {
c.JSON(http.StatusForbidden, gin.H{"error": "需要管理员权限"})
c.Abort()
return
}
c.Next()
}
}

View File

@@ -0,0 +1,62 @@
package middleware
import (
"licserver/internal/utils"
"net/http"
"github.com/gin-gonic/gin"
)
func ErrorHandler() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
// 只处理第一个错误
if len(c.Errors) > 0 {
err := c.Errors[0].Err
var statusCode int
var response utils.ErrorResponse
switch err {
case utils.ErrUnauthorized:
statusCode = http.StatusUnauthorized
response = utils.ErrorResponse{
Code: 401,
Message: "未授权的访问",
Detail: err.Error(),
}
case utils.ErrForbidden:
statusCode = http.StatusForbidden
response = utils.ErrorResponse{
Code: 403,
Message: "禁止访问",
Detail: err.Error(),
}
case utils.ErrNotFound:
statusCode = http.StatusNotFound
response = utils.ErrorResponse{
Code: 404,
Message: "资源不存在",
Detail: err.Error(),
}
case utils.ErrInvalidInput:
statusCode = http.StatusBadRequest
response = utils.ErrorResponse{
Code: 400,
Message: "无效的输入",
Detail: err.Error(),
}
default:
statusCode = http.StatusInternalServerError
response = utils.ErrorResponse{
Code: 500,
Message: "服务器内部错误",
Detail: err.Error(),
}
}
c.JSON(statusCode, response)
c.Abort()
}
}
}