Files
terminal/server/app/middleware/auth.go
T

160 lines
5.0 KiB
Go

package middleware
import (
"next-terminal/server/common/nt"
"strings"
"next-terminal/server/api"
"next-terminal/server/dto"
"next-terminal/server/global/cache"
"next-terminal/server/service"
"github.com/labstack/echo/v4"
"github.com/ucarion/urlpath"
)
var anonymousUrls = []string{"/login", "/static", "/favicon.ico", "/logo.svg", "/logo", "/branding", "/api/branding", "/api/logo", "/setup-status", "/setup-user", "/api/admin/setup-status", "/api/admin/login", "/api/admin/setup-user", "/api/admin/login-status", "/api/login-status", "/api/admin/captcha", "/api/captcha", "/captcha"}
var allowUrls = []urlpath.Path{
urlpath.New("/api/admin/account/info"),
urlpath.New("/api/admin/account/storage"),
urlpath.New("/api/admin/account/logout"),
urlpath.New("/api/admin/account/change-password"),
urlpath.New("/api/admin/account/reload-totp"),
urlpath.New("/api/admin/account/reset-totp"),
urlpath.New("/api/admin/account/confirm-totp"),
urlpath.New("/api/admin/account/access-token"),
urlpath.New("/api/admin/account/security-token/support-types"),
urlpath.New("/api/admin/account/security-token/mfa"),
urlpath.New("/api/admin/account/security-token/validate"),
urlpath.New("/api/admin/account/client-cert"),
urlpath.New("/api/admin/account/client-cert/download"),
urlpath.New("/api/admin/account/webauthn/credentials"),
urlpath.New("/api/admin/account/webauthn/credentials/:id"),
urlpath.New("/api/admin/account/webauthn/credentials/start"),
urlpath.New("/api/admin/account/webauthn/credentials/finish"),
urlpath.New("/api/admin/account/oidc-server-consents"),
urlpath.New("/api/admin/account/oidc-server-consents/:id"),
urlpath.New("/share-sessions/:id"),
urlpath.New("/api/admin/sessions"),
urlpath.New("/api/admin/sessions/:id/tunnel"),
urlpath.New("/api/admin/sessions/:id/connect"),
urlpath.New("/api/admin/sessions/:id/resize"),
urlpath.New("/api/admin/sessions/:id/stats"),
urlpath.New("/api/admin/sessions/:id/ls"),
urlpath.New("/api/admin/sessions/:id/download"),
urlpath.New("/api/admin/sessions/:id/upload"),
urlpath.New("/api/admin/sessions/:id/edit"),
urlpath.New("/api/admin/sessions/:id/mkdir"),
urlpath.New("/api/admin/sessions/:id/rm"),
urlpath.New("/api/admin/sessions/:id/rename"),
urlpath.New("/api/admin/sessions/:id/ssh"),
urlpath.New("/api/portal/assets"),
urlpath.New("/api/portal/database-assets"),
urlpath.New("/api/portal/assets/tree"),
urlpath.New("/api/portal/websites/tree"),
urlpath.New("/api/portal/assets/group-tree"),
urlpath.New("/api/portal/websites"),
urlpath.New("/api/portal/info"),
urlpath.New("/api/license"),
urlpath.New("/api/admin/tools/tcping"),
urlpath.New("/api/admin/tools/ping"),
}
func Auth(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
uri := c.Request().RequestURI
if uri == "/" || strings.HasPrefix(uri, "/#") {
return next(c)
}
// 路由拦截 - 登录身份、资源权限判断等
for i := range anonymousUrls {
if strings.HasPrefix(uri, anonymousUrls[i]) {
return next(c)
}
}
token := api.GetToken(c)
if token == "" {
return api.Fail(c, 401, "您的登录信息已失效,请重新登录后再试。")
}
v, found := cache.TokenManager.Get(token)
if !found {
return api.Fail(c, 401, "您的登录信息已失效,请重新登录后再试。")
}
authorization := v.(dto.Authorization)
if strings.EqualFold(nt.LoginToken, authorization.Type) {
if authorization.Remember {
// 记住登录有效期两周
cache.TokenManager.Set(token, authorization, cache.RememberMeExpiration)
} else {
cache.TokenManager.Set(token, authorization, cache.NotRememberExpiration)
}
}
// 放行接入相关接口
uriPath := strings.Split(uri, "?")[0]
for _, url := range allowUrls {
_, ok := url.Match(uriPath)
if ok {
return next(c)
}
}
account, _ := api.GetCurrentAccount(c)
if service.UserService.IsSuperAdmin(account.ID) {
return next(c)
}
var roles []string
v, ok := cache.UserRolesManager.Get(account.ID)
if ok {
roles = v.([]string)
if len(roles) == 0 {
roles, _ = service.RoleService.GetRolesByUserId(account.ID)
cache.UserRolesManager.SetDefault(account.ID, roles)
}
} else {
roles, _ = service.RoleService.GetRolesByUserId(account.ID)
cache.UserRolesManager.SetDefault(account.ID, roles)
}
urlPath := c.Request().URL.Path
for _, role := range roles {
menus := service.RoleService.GetMenuListByRole(role)
for _, menu := range menus {
permissions := service.MenuService.GetPermissionByMenu(menu)
for _, perm := range permissions {
_, ok := perm.Match(urlPath)
if ok {
return next(c)
}
}
}
}
return api.Fail(c, 403, "permission denied")
}
}
func Admin(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
account, found := api.GetCurrentAccount(c)
if !found {
return api.Fail(c, 401, "您的登录信息已失效,请重新登录后再试。")
}
if account.Type != nt.TypeAdmin {
return api.Fail(c, 403, "permission denied.")
}
return next(c)
}
}