mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 07:57:21 +08:00
refactor: 使用session鉴权
This commit is contained in:
@@ -2,7 +2,6 @@ package controllers
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/swaggo/http-swagger/v2"
|
||||
|
||||
_ "github.com/TheTNB/panel/docs"
|
||||
@@ -25,10 +24,6 @@ func NewSwaggerController() *SwaggerController {
|
||||
// @Failure 500
|
||||
// @Router /swagger [get]
|
||||
func (r *SwaggerController) Index(ctx http.Context) http.Response {
|
||||
if !facades.Config().GetBool("app.debug") {
|
||||
return Error(ctx, http.StatusNotFound, http.StatusText(http.StatusNotFound))
|
||||
}
|
||||
|
||||
handler := httpSwagger.Handler()
|
||||
handler(ctx.Response().Writer(), ctx.Request().Origin())
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"github.com/TheTNB/panel/app/http/requests/user"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
@@ -20,16 +23,15 @@ func NewUserController() *UserController {
|
||||
|
||||
// Login
|
||||
//
|
||||
// @Summary 登录
|
||||
// @Description 通过用户名和密码获取访问令牌
|
||||
// @Tags 用户鉴权
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body requests.Login true "request"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 403 {object} ErrorResponse "用户名或密码错误"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误
|
||||
// @Router /panel/user/login [post]
|
||||
// @Summary 登录
|
||||
// @Tags 用户鉴权
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body requests.Login true "request"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 403 {object} ErrorResponse "用户名或密码错误"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误
|
||||
// @Router /panel/user/login [post]
|
||||
func (r *UserController) Login(ctx http.Context) http.Response {
|
||||
var loginRequest requests.Login
|
||||
sanitize := SanitizeRequest(ctx, &loginRequest)
|
||||
@@ -60,32 +62,38 @@ func (r *UserController) Login(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
token, loginErr := facades.Auth(ctx).LoginUsingID(user.ID)
|
||||
if loginErr != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "用户").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("登录失败")
|
||||
return ErrorSystem(ctx)
|
||||
ctx.Request().Session().Put("user_id", user.ID)
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// Logout
|
||||
//
|
||||
// @Summary 登出
|
||||
// @Tags 用户鉴权
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Router /panel/user/logout [post]
|
||||
func (r *UserController) Logout(ctx http.Context) http.Response {
|
||||
if err := ctx.Request().Session().Invalidate(); err != nil {
|
||||
return Error(ctx, http.StatusInternalServerError, fmt.Sprintf("登出失败: %s", err.Error()))
|
||||
}
|
||||
|
||||
return Success(ctx, http.Json{
|
||||
"access_token": token,
|
||||
})
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// Info
|
||||
//
|
||||
// @Summary 用户信息
|
||||
// @Description 获取当前登录用户信息
|
||||
// @Tags 用户鉴权
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Router /panel/user/info [get]
|
||||
// @Summary 用户信息
|
||||
// @Tags 用户鉴权
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Router /panel/user/info [get]
|
||||
func (r *UserController) Info(ctx http.Context) http.Response {
|
||||
userID := cast.ToUint(ctx.Value("user_id"))
|
||||
var user models.User
|
||||
err := facades.Auth(ctx).User(&user)
|
||||
if err != nil {
|
||||
if err := facades.Orm().Query().Where("id", userID).Get(&user); err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "用户").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("获取用户信息失败")
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/goravel/framework/auth"
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
)
|
||||
|
||||
// Jwt 确保通过 JWT 鉴权
|
||||
func Jwt() http.Middleware {
|
||||
return func(ctx http.Context) {
|
||||
translate := facades.Lang(ctx)
|
||||
token := ctx.Request().Header("Authorization", ctx.Request().Header("Sec-WebSocket-Protocol"))
|
||||
if len(token) == 0 {
|
||||
ctx.Request().AbortWithStatusJson(http.StatusUnauthorized, http.Json{
|
||||
"message": translate.Get("auth.token.missing"),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// JWT 鉴权
|
||||
if _, err := facades.Auth(ctx).Parse(token); err != nil {
|
||||
if errors.Is(err, auth.ErrorTokenExpired) {
|
||||
token, err = facades.Auth(ctx).Refresh()
|
||||
if err != nil {
|
||||
// 到达刷新时间上限
|
||||
ctx.Request().AbortWithStatusJson(http.StatusUnauthorized, http.Json{
|
||||
"message": translate.Get("auth.token.expired"),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
token = "Bearer " + token
|
||||
} else {
|
||||
ctx.Request().AbortWithStatusJson(http.StatusUnauthorized, http.Json{
|
||||
"message": translate.Get("auth.token.expired"),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Response().Header("Authorization", token)
|
||||
ctx.Request().Next()
|
||||
}
|
||||
}
|
||||
39
app/http/middleware/session.go
Normal file
39
app/http/middleware/session.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
// Session 确保通过 JWT 鉴权
|
||||
func Session() http.Middleware {
|
||||
return func(ctx http.Context) {
|
||||
translate := facades.Lang(ctx)
|
||||
|
||||
if !ctx.Request().HasSession() {
|
||||
ctx.Request().AbortWithStatusJson(http.StatusUnauthorized, http.Json{
|
||||
"message": translate.Get("auth.session.missing"),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.Request().Session().Missing("user_id") {
|
||||
ctx.Request().AbortWithStatusJson(http.StatusUnauthorized, http.Json{
|
||||
"message": translate.Get("auth.session.expired"),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
userID := cast.ToUint(ctx.Request().Session().Get("user_id"))
|
||||
if userID == 0 {
|
||||
ctx.Request().AbortWithStatusJson(http.StatusUnauthorized, http.Json{
|
||||
"message": translate.Get("auth.session.invalid"),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ctx.WithValue("user_id", userID)
|
||||
ctx.Request().Next()
|
||||
}
|
||||
}
|
||||
26
docs/docs.go
26
docs/docs.go
@@ -3235,7 +3235,6 @@ const docTemplate = `{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "获取当前登录用户信息",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
@@ -3255,7 +3254,6 @@ const docTemplate = `{
|
||||
},
|
||||
"/panel/user/login": {
|
||||
"post": {
|
||||
"description": "通过用户名和密码获取访问令牌",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
@@ -3299,6 +3297,30 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/panel/user/logout": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"用户鉴权"
|
||||
],
|
||||
"summary": "登出",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/panel/website/backupList": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
||||
@@ -3228,7 +3228,6 @@
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "获取当前登录用户信息",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
@@ -3248,7 +3247,6 @@
|
||||
},
|
||||
"/panel/user/login": {
|
||||
"post": {
|
||||
"description": "通过用户名和密码获取访问令牌",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
@@ -3292,6 +3290,30 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/panel/user/logout": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"用户鉴权"
|
||||
],
|
||||
"summary": "登出",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/panel/website/backupList": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
||||
@@ -2645,7 +2645,6 @@ paths:
|
||||
- 系统
|
||||
/panel/user/info:
|
||||
get:
|
||||
description: 获取当前登录用户信息
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -2662,7 +2661,6 @@ paths:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 通过用户名和密码获取访问令牌
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
@@ -2688,6 +2686,20 @@ paths:
|
||||
summary: 登录
|
||||
tags:
|
||||
- 用户鉴权
|
||||
/panel/user/logout:
|
||||
post:
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 登出
|
||||
tags:
|
||||
- 用户鉴权
|
||||
/panel/website/backupList:
|
||||
get:
|
||||
parameters:
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"auth": {
|
||||
"token": {
|
||||
"expired": "login has expired",
|
||||
"missing": "not logged in"
|
||||
"session": {
|
||||
"expired": "session has expired",
|
||||
"missing": "Please enable cookies and try again",
|
||||
"invalid": "invalid session"
|
||||
}
|
||||
},
|
||||
"commands": {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"auth": {
|
||||
"token": {
|
||||
"expired": "登录已过期",
|
||||
"missing": "未登录"
|
||||
"session": {
|
||||
"expired": "会话已过期",
|
||||
"missing": "请启用 Cookie 后再试",
|
||||
"invalid": "会话无效"
|
||||
}
|
||||
},
|
||||
"commands": {
|
||||
|
||||
@@ -14,29 +14,30 @@ func Api() {
|
||||
r.Prefix("info").Group(func(r route.Router) {
|
||||
infoController := controllers.NewInfoController()
|
||||
r.Get("panel", infoController.Panel)
|
||||
r.Middleware(middleware.Jwt()).Get("homePlugins", infoController.HomePlugins)
|
||||
r.Middleware(middleware.Jwt()).Get("nowMonitor", infoController.NowMonitor)
|
||||
r.Middleware(middleware.Jwt()).Get("systemInfo", infoController.SystemInfo)
|
||||
r.Middleware(middleware.Jwt()).Get("countInfo", infoController.CountInfo)
|
||||
r.Middleware(middleware.Jwt()).Get("installedDbAndPhp", infoController.InstalledDbAndPhp)
|
||||
r.Middleware(middleware.Jwt()).Get("checkUpdate", infoController.CheckUpdate)
|
||||
r.Middleware(middleware.Jwt()).Get("updateInfo", infoController.UpdateInfo)
|
||||
r.Middleware(middleware.Jwt()).Post("update", infoController.Update)
|
||||
r.Middleware(middleware.Jwt()).Post("restart", infoController.Restart)
|
||||
r.Middleware(middleware.Session()).Get("homePlugins", infoController.HomePlugins)
|
||||
r.Middleware(middleware.Session()).Get("nowMonitor", infoController.NowMonitor)
|
||||
r.Middleware(middleware.Session()).Get("systemInfo", infoController.SystemInfo)
|
||||
r.Middleware(middleware.Session()).Get("countInfo", infoController.CountInfo)
|
||||
r.Middleware(middleware.Session()).Get("installedDbAndPhp", infoController.InstalledDbAndPhp)
|
||||
r.Middleware(middleware.Session()).Get("checkUpdate", infoController.CheckUpdate)
|
||||
r.Middleware(middleware.Session()).Get("updateInfo", infoController.UpdateInfo)
|
||||
r.Middleware(middleware.Session()).Post("update", infoController.Update)
|
||||
r.Middleware(middleware.Session()).Post("restart", infoController.Restart)
|
||||
})
|
||||
r.Prefix("user").Group(func(r route.Router) {
|
||||
userController := controllers.NewUserController()
|
||||
r.Middleware(frameworkmiddleware.Throttle("login")).Post("login", userController.Login)
|
||||
r.Middleware(middleware.Jwt()).Get("info", userController.Info)
|
||||
r.Post("logout", userController.Logout)
|
||||
r.Middleware(middleware.Session()).Get("info", userController.Info)
|
||||
})
|
||||
r.Prefix("task").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
r.Prefix("task").Middleware(middleware.Session()).Group(func(r route.Router) {
|
||||
taskController := controllers.NewTaskController()
|
||||
r.Get("status", taskController.Status)
|
||||
r.Get("list", taskController.List)
|
||||
r.Get("log", taskController.Log)
|
||||
r.Post("delete", taskController.Delete)
|
||||
})
|
||||
r.Prefix("website").Middleware(middleware.Jwt(), middleware.MustInstall()).Group(func(r route.Router) {
|
||||
r.Prefix("website").Middleware(middleware.Session(), middleware.MustInstall()).Group(func(r route.Router) {
|
||||
websiteController := controllers.NewWebsiteController()
|
||||
r.Get("defaultConfig", websiteController.GetDefaultConfig)
|
||||
r.Post("defaultConfig", websiteController.SaveDefaultConfig)
|
||||
@@ -44,7 +45,7 @@ func Api() {
|
||||
r.Put("uploadBackup", websiteController.UploadBackup)
|
||||
r.Delete("deleteBackup", websiteController.DeleteBackup)
|
||||
})
|
||||
r.Prefix("websites").Middleware(middleware.Jwt(), middleware.MustInstall()).Group(func(r route.Router) {
|
||||
r.Prefix("websites").Middleware(middleware.Session(), middleware.MustInstall()).Group(func(r route.Router) {
|
||||
websiteController := controllers.NewWebsiteController()
|
||||
r.Get("/", websiteController.List)
|
||||
r.Post("/", websiteController.Add)
|
||||
@@ -58,7 +59,7 @@ func Api() {
|
||||
r.Post("{id}/resetConfig", websiteController.ResetConfig)
|
||||
r.Post("{id}/status", websiteController.Status)
|
||||
})
|
||||
r.Prefix("cert").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
r.Prefix("cert").Middleware(middleware.Session()).Group(func(r route.Router) {
|
||||
certController := controllers.NewCertController()
|
||||
r.Get("caProviders", certController.CAProviders)
|
||||
r.Get("dnsProviders", certController.DNSProviders)
|
||||
@@ -83,7 +84,7 @@ func Api() {
|
||||
r.Post("manualDNS", certController.ManualDNS)
|
||||
r.Post("deploy", certController.Deploy)
|
||||
})
|
||||
r.Prefix("plugin").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
r.Prefix("plugin").Middleware(middleware.Session()).Group(func(r route.Router) {
|
||||
pluginController := controllers.NewPluginController()
|
||||
r.Get("list", pluginController.List)
|
||||
r.Post("install", pluginController.Install)
|
||||
@@ -92,7 +93,7 @@ func Api() {
|
||||
r.Post("updateShow", pluginController.UpdateShow)
|
||||
r.Get("isInstalled", pluginController.IsInstalled)
|
||||
})
|
||||
r.Prefix("cron").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
r.Prefix("cron").Middleware(middleware.Session()).Group(func(r route.Router) {
|
||||
cronController := controllers.NewCronController()
|
||||
r.Get("list", cronController.List)
|
||||
r.Get("{id}", cronController.Script)
|
||||
@@ -102,7 +103,7 @@ func Api() {
|
||||
r.Post("status", cronController.Status)
|
||||
r.Get("log/{id}", cronController.Log)
|
||||
})
|
||||
r.Prefix("safe").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
r.Prefix("safe").Middleware(middleware.Session()).Group(func(r route.Router) {
|
||||
safeController := controllers.NewSafeController()
|
||||
r.Get("firewallStatus", safeController.GetFirewallStatus)
|
||||
r.Post("firewallStatus", safeController.SetFirewallStatus)
|
||||
@@ -116,7 +117,7 @@ func Api() {
|
||||
r.Get("pingStatus", safeController.GetPingStatus)
|
||||
r.Post("pingStatus", safeController.SetPingStatus)
|
||||
})
|
||||
r.Prefix("container").Middleware(middleware.Jwt(), middleware.MustInstall()).Group(func(r route.Router) {
|
||||
r.Prefix("container").Middleware(middleware.Session(), middleware.MustInstall()).Group(func(r route.Router) {
|
||||
containerController := controllers.NewContainerController()
|
||||
r.Get("list", containerController.ContainerList)
|
||||
r.Get("search", containerController.ContainerSearch)
|
||||
@@ -164,7 +165,7 @@ func Api() {
|
||||
r.Post("prune", containerController.VolumePrune)
|
||||
})
|
||||
})
|
||||
r.Prefix("file").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
r.Prefix("file").Middleware(middleware.Session()).Group(func(r route.Router) {
|
||||
fileController := controllers.NewFileController()
|
||||
r.Post("create", fileController.Create)
|
||||
r.Get("content", fileController.Content)
|
||||
@@ -182,7 +183,7 @@ func Api() {
|
||||
r.Post("search", fileController.Search)
|
||||
r.Get("list", fileController.List)
|
||||
})
|
||||
r.Prefix("monitor").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
r.Prefix("monitor").Middleware(middleware.Session()).Group(func(r route.Router) {
|
||||
monitorController := controllers.NewMonitorController()
|
||||
r.Post("switch", monitorController.Switch)
|
||||
r.Post("saveDays", monitorController.SaveDays)
|
||||
@@ -190,20 +191,20 @@ func Api() {
|
||||
r.Get("list", monitorController.List)
|
||||
r.Get("switchAndDays", monitorController.SwitchAndDays)
|
||||
})
|
||||
r.Prefix("ssh").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
r.Prefix("ssh").Middleware(middleware.Session()).Group(func(r route.Router) {
|
||||
sshController := controllers.NewSshController()
|
||||
r.Get("info", sshController.GetInfo)
|
||||
r.Post("info", sshController.UpdateInfo)
|
||||
r.Get("session", sshController.Session)
|
||||
})
|
||||
r.Prefix("setting").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
r.Prefix("setting").Middleware(middleware.Session()).Group(func(r route.Router) {
|
||||
settingController := controllers.NewSettingController()
|
||||
r.Get("list", settingController.List)
|
||||
r.Post("update", settingController.Update)
|
||||
r.Get("https", settingController.GetHttps)
|
||||
r.Post("https", settingController.UpdateHttps)
|
||||
})
|
||||
r.Prefix("system").Middleware(middleware.Jwt()).Group(func(r route.Router) {
|
||||
r.Prefix("system").Middleware(middleware.Session()).Group(func(r route.Router) {
|
||||
controller := controllers.NewSystemController()
|
||||
r.Get("service/status", controller.ServiceStatus)
|
||||
r.Get("service/isEnabled", controller.ServiceIsEnabled)
|
||||
@@ -218,7 +219,7 @@ func Api() {
|
||||
|
||||
// 文档
|
||||
swaggerController := controllers.NewSwaggerController()
|
||||
facades.Route().Get("swagger/*any", swaggerController.Index)
|
||||
facades.Route().Middleware(middleware.Session()).Get("swagger/*any", swaggerController.Index)
|
||||
|
||||
// 静态文件
|
||||
entrance := facades.Config().GetString("http.entrance")
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// Plugin 加载插件路由
|
||||
func Plugin() {
|
||||
facades.Route().Prefix("api/plugins").Middleware(middleware.Jwt(), middleware.MustInstall()).Group(func(r route.Router) {
|
||||
facades.Route().Prefix("api/plugins").Middleware(middleware.Session(), middleware.MustInstall()).Group(func(r route.Router) {
|
||||
r.Prefix("openresty").Group(func(route route.Router) {
|
||||
openRestyController := plugins.NewOpenrestyController()
|
||||
route.Get("load", openRestyController.Load)
|
||||
|
||||
Reference in New Issue
Block a user