package admin import ( "encoding/hex" "errors" "fmt" "net/http" "strings" "time" "git.pyer.club/kingecg/gohttpd/model" "git.pyer.club/kingecg/gohttpd/server" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) type LoginModel struct { Username string `json:"username"` Encrypt string `json:"password"` } // login 处理用户登录请求,验证凭证并生成会话令牌。 // 参数: // // w: HTTP响应写入器,用于返回响应状态和数据。 // r: 指向HTTP请求的指针,包含请求上下文和数据。 // // 返回值: // // 无直接返回值,通过w写入HTTP响应。 func login(c *gin.Context) { // 从请求上下文中获取请求数据 // ctx := c.Request.Context() // ctxData := ctx.Value(server.RequestCtxKey("data")).(map[string]interface{}) // data, ok := ctxData["data"] loginModel := LoginModel{} // 绑定请求体到LoginModel结构体 if err := c.ShouldBindJSON(&loginModel); err != nil { c.Writer.WriteHeader(http.StatusBadRequest) c.Writer.Write(server.NewErrorResult(err)) return } // 验证是否为管理员账号 if loginModel.Username == "admin" { // 解密密码并验证与配置文件中密码是否匹配 decryptText, _ := Decrypt(loginModel.Encrypt) if decryptText == model.GetConfig().Admin.Password { // 生成JWT令牌 token, err := GenerateToken(loginModel.Username) if err != nil { c.Writer.WriteHeader(http.StatusInternalServerError) c.Writer.Write(server.NewErrorResult(err)) return } // 设置认证Cookie并返回成功响应 cookie := &http.Cookie{ Name: "token", Value: token, Path: "/", SameSite: http.SameSiteStrictMode, Expires: time.Now().Add(time.Hour * 24 * 7), } c.Writer.Header().Set("Set-Cookie", cookie.String()) c.Writer.WriteHeader(http.StatusOK) c.Writer.Write(server.NewSuccessResult("Login success")) return } } else { // 非管理员账号返回禁止访问响应 c.Writer.WriteHeader(http.StatusForbidden) resp := server.NewErrorResult(errors.New("not allowed user/password")) c.Writer.Write(resp) return } // 默认返回未授权响应 c.Writer.WriteHeader(http.StatusUnauthorized) c.Writer.Write(server.NewErrorResult(errors.New("not allowed user/password"))) } // 实现非对称加密 func Encrypt(plaintext string) (string, error) { ciphertext := make([]byte, len(plaintext)) for i := 0; i < len(plaintext); i++ { ciphertext[i] = plaintext[i] ^ 0xFF } return string(ciphertext), nil } // 实现非对称解密 func Decrypt(ciphertext string) (string, error) { plaintext := make([]byte, 1) cipbyte := []byte(ciphertext) // 每次取前2字节 for i := 0; i < len(cipbyte); i += 2 { d := cipbyte[i : i+2] // 转成16进制 dd, err := hex.DecodeString(string(d)) if err != nil { return "", err } // 异或 plaintext = append(plaintext, dd[0]^0xFF) } //去除末尾13个字节 plaintext = plaintext[1 : len(plaintext)-13] return string(plaintext), nil } // 生成token func GenerateToken(username string) (string, error) { // jwt token jwtConfig := model.GetConfig().Admin.Jwt secret := jwtConfig.Secret expire := jwtConfig.Expire issuer := jwtConfig.Issuer audience := jwtConfig.Audience claim := &jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expire) * time.Hour)), Issuer: issuer, Audience: []string{audience}, IssuedAt: jwt.NewNumericDate(time.Now()), Subject: username, } // 生成token token := jwt.NewWithClaims(jwt.SigningMethodHS256, claim) return token.SignedString([]byte(secret)) } func ginBashiAuth(c *gin.Context) { // first get Url url := c.Request.URL.Path // check if url is login if strings.Contains(url, "login") || strings.Contains(url, "logout") { c.Next() return } accountMap := map[string]string{} accountMap[model.GetConfig().Admin.Username] = model.GetConfig().Admin.Password handler := gin.BasicAuth(accountMap) // 使用gin的BasicAuth中间件进行认证 handler(c) // 调用认证处理函数 } func jwtAuth(c *gin.Context) { config := model.GetConfig().Admin if config == nil || config.Jwt == nil { c.AbortWithError(http.StatusInternalServerError, errors.New("Jwt config error")) // http.Error(w, "Jwt config error", http.StatusInternalServerError) return } url := c.Request.URL.Path // check if url is login if strings.Contains(url, "login") || strings.Contains(url, "logout") { c.Next() return } jwtConfig := config.Jwt if jwtConfig.Secret == "" { c.Next() return } // 从cookie中获取token tokenCookie, err := c.Cookie("auth_token") //r.Cookie("auth_token") if err != nil { c.AbortWithStatus(http.StatusUnauthorized) return } tokenString := tokenCookie token, err := jwt.ParseWithClaims(tokenString, &jwt.RegisteredClaims{}, func(token *jwt.Token) (interface{}, error) { // 确保签名方法是正确的 if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } return []byte(jwtConfig.Secret), nil }) if err != nil { // l.Error("Failed to parse JWT: %v", err) c.AbortWithStatus(http.StatusUnauthorized) return } if claims, ok := token.Claims.(*jwt.RegisteredClaims); ok && token.Valid { // 验证通过,将用户信息存储在请求上下文中 // ctx := context.WithValue(r.Context(), "user", claims) // next.ServeHTTP(w, r.WithContext(ctx)) c.Set("user", claims) return } c.AbortWithStatus(http.StatusUnauthorized) // http.Error(w, "Unauthorized.", http.StatusUnauthorized) }