mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
feat(system-security): Optimized unauthenticated settings to enhance system security (#7532)
This commit is contained in:
parent
75142b33a4
commit
909b10f422
@ -25,6 +25,8 @@ type IAuthService interface {
|
|||||||
Login(c *gin.Context, info dto.Login, entrance string) (*dto.UserLoginInfo, error)
|
Login(c *gin.Context, info dto.Login, entrance string) (*dto.UserLoginInfo, error)
|
||||||
LogOut(c *gin.Context) error
|
LogOut(c *gin.Context) error
|
||||||
MFALogin(c *gin.Context, info dto.MFALogin, entrance string) (*dto.UserLoginInfo, error)
|
MFALogin(c *gin.Context, info dto.MFALogin, entrance string) (*dto.UserLoginInfo, error)
|
||||||
|
GetSecurityEntrance() string
|
||||||
|
IsLogin(c *gin.Context) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIAuthService() IAuthService {
|
func NewIAuthService() IAuthService {
|
||||||
@ -192,3 +194,19 @@ func (u *AuthService) GetResponsePage() (string, error) {
|
|||||||
}
|
}
|
||||||
return pageCode.Value, nil
|
return pageCode.Value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *AuthService) GetSecurityEntrance() string {
|
||||||
|
status, err := settingRepo.Get(repo.WithByKey("SecurityEntrance"))
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if len(status.Value) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return status.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *AuthService) IsLogin(c *gin.Context) bool {
|
||||||
|
_, err := global.SESSION.Get(c)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
6
core/cmd/server/res/error_msg.go
Normal file
6
core/cmd/server/res/error_msg.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package res
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
//go:embed html/*
|
||||||
|
var ErrorMsg embed.FS
|
55
core/cmd/server/res/html/200.html
Normal file
55
core/cmd/server/res/html/200.html
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Access Temporarily Unavailable</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 50px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
.icon img {
|
||||||
|
width: 100px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.command {
|
||||||
|
font-family: monospace;
|
||||||
|
background: #f0f0f0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Access Temporarily Unavailable</h1>
|
||||||
|
<p>The current environment has enabled secure login access.</p>
|
||||||
|
<p>Run the following SSH command to view the panel login URL:</p>
|
||||||
|
<p class="command">1pctl user-info</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
55
core/cmd/server/res/html/200_err_domain.html
Normal file
55
core/cmd/server/res/html/200_err_domain.html
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Access Temporarily Unavailable</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 50px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
.icon img {
|
||||||
|
width: 100px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.command {
|
||||||
|
font-family: monospace;
|
||||||
|
background: #f0f0f0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Access Temporarily Unavailable</h1>
|
||||||
|
<p>The current environment has enabled domain name binding.</p>
|
||||||
|
<p>Run the following SSH command to reset the binding information:</p>
|
||||||
|
<p class="command">1pctl reset domain</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
55
core/cmd/server/res/html/200_err_ip_limit.html
Normal file
55
core/cmd/server/res/html/200_err_ip_limit.html
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Access Temporarily Unavailable</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 50px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
.icon img {
|
||||||
|
width: 100px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.command {
|
||||||
|
font-family: monospace;
|
||||||
|
background: #f0f0f0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Access Temporarily Unavailable</h1>
|
||||||
|
<p>The current environment has enabled authorized IP access.</p>
|
||||||
|
<p>Run the following SSH command to reset the binding information:</p>
|
||||||
|
<p class="command">1pctl reset ips</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
7
core/cmd/server/res/html/400.html
Normal file
7
core/cmd/server/res/html/400.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head><title>400 Bad Request</title></head>
|
||||||
|
<body>
|
||||||
|
<center><h1>400 Bad Request</h1></center>
|
||||||
|
<hr><center>nginx</center>
|
||||||
|
</body>
|
7
core/cmd/server/res/html/401.html
Normal file
7
core/cmd/server/res/html/401.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head><title>401 Unauthorized</title></head>
|
||||||
|
<body>
|
||||||
|
<center><h1>401 Unauthorized</h1></center>
|
||||||
|
<hr><center>nginx</center>
|
||||||
|
</body>
|
7
core/cmd/server/res/html/403.html
Normal file
7
core/cmd/server/res/html/403.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head><title>403 Forbidden</title></head>
|
||||||
|
<body>
|
||||||
|
<center><h1>403 Forbidden</h1></center>
|
||||||
|
<hr><center>nginx</center>
|
||||||
|
</body>
|
7
core/cmd/server/res/html/404.html
Normal file
7
core/cmd/server/res/html/404.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head><title>404 Not Found</title></head>
|
||||||
|
<body>
|
||||||
|
<center><h1>404 Not Found</h1></center>
|
||||||
|
<hr><center>nginx</center>
|
||||||
|
</body>
|
7
core/cmd/server/res/html/408.html
Normal file
7
core/cmd/server/res/html/408.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head><title>408 Request Timeout</title></head>
|
||||||
|
<body>
|
||||||
|
<center><h1>408 Request Timeout</h1></center>
|
||||||
|
<hr><center>nginx</center>
|
||||||
|
</body>
|
7
core/cmd/server/res/html/416.html
Normal file
7
core/cmd/server/res/html/416.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head><title>416 Requested Not Satisfiable</title></head>
|
||||||
|
<body>
|
||||||
|
<center><h1>416 Requested Not Satisfiable</h1></center>
|
||||||
|
<hr><center>nginx</center>
|
||||||
|
</body>
|
7
core/cmd/server/res/html/500.html
Normal file
7
core/cmd/server/res/html/500.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head><title>Internal Server Error</title></head>
|
||||||
|
<body>
|
||||||
|
<center><h1>Internal Server Error</h1></center>
|
||||||
|
<hr><center>nginx</center>
|
||||||
|
</body>
|
@ -40,4 +40,105 @@ const (
|
|||||||
FilePerm = 0644
|
FilePerm = 0644
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var WebUrlMap = map[string]struct{}{
|
||||||
|
"/apps": {},
|
||||||
|
"/apps/all": {},
|
||||||
|
"/apps/installed": {},
|
||||||
|
"/apps/upgrade": {},
|
||||||
|
|
||||||
|
"/containers": {},
|
||||||
|
"/containers/container": {},
|
||||||
|
"/containers/image": {},
|
||||||
|
"/containers/network": {},
|
||||||
|
"/containers/volume": {},
|
||||||
|
"/containers/repo": {},
|
||||||
|
"/containers/compose": {},
|
||||||
|
"/containers/template": {},
|
||||||
|
"/containers/setting": {},
|
||||||
|
|
||||||
|
"/cronjobs": {},
|
||||||
|
|
||||||
|
"/databases": {},
|
||||||
|
"/databases/mysql": {},
|
||||||
|
"/databases/mysql/remote": {},
|
||||||
|
"/databases/postgresql": {},
|
||||||
|
"/databases/postgresql/remote": {},
|
||||||
|
"/databases/redis": {},
|
||||||
|
"/databases/redis/remote": {},
|
||||||
|
|
||||||
|
"/hosts": {},
|
||||||
|
"/hosts/files": {},
|
||||||
|
"/hosts/monitor/monitor": {},
|
||||||
|
"/hosts/monitor/setting": {},
|
||||||
|
"/hosts/terminal": {},
|
||||||
|
"/hosts/firewall/port": {},
|
||||||
|
"/hosts/firewall/forward": {},
|
||||||
|
"/hosts/firewall/ip": {},
|
||||||
|
"/hosts/process/process": {},
|
||||||
|
"/hosts/process/network": {},
|
||||||
|
"/hosts/ssh/ssh": {},
|
||||||
|
"/hosts/ssh/log": {},
|
||||||
|
"/hosts/ssh/session": {},
|
||||||
|
|
||||||
|
"/logs": {},
|
||||||
|
"/logs/operation": {},
|
||||||
|
"/logs/login": {},
|
||||||
|
"/logs/website": {},
|
||||||
|
"/logs/system": {},
|
||||||
|
"/logs/ssh": {},
|
||||||
|
|
||||||
|
"/settings": {},
|
||||||
|
"/settings/panel": {},
|
||||||
|
"/settings/backupaccount": {},
|
||||||
|
"/settings/license": {},
|
||||||
|
"/settings/about": {},
|
||||||
|
"/settings/safe": {},
|
||||||
|
"/settings/snapshot": {},
|
||||||
|
"/settings/expired": {},
|
||||||
|
|
||||||
|
"/toolbox": {},
|
||||||
|
"/toolbox/device": {},
|
||||||
|
"/toolbox/supervisor": {},
|
||||||
|
"/toolbox/clam": {},
|
||||||
|
"/toolbox/clam/setting": {},
|
||||||
|
"/toolbox/ftp": {},
|
||||||
|
"/toolbox/fail2ban": {},
|
||||||
|
"/toolbox/clean": {},
|
||||||
|
|
||||||
|
"/websites": {},
|
||||||
|
"/websites/ssl": {},
|
||||||
|
"/websites/runtimes/php": {},
|
||||||
|
"/websites/runtimes/node": {},
|
||||||
|
"/websites/runtimes/java": {},
|
||||||
|
"/websites/runtimes/go": {},
|
||||||
|
"/websites/runtimes/python": {},
|
||||||
|
"/websites/runtimes/dotnet": {},
|
||||||
|
|
||||||
|
"/login": {},
|
||||||
|
|
||||||
|
"/xpack": {},
|
||||||
|
"/xpack/waf/dashboard": {},
|
||||||
|
"/xpack/waf/global": {},
|
||||||
|
"/xpack/waf/websites": {},
|
||||||
|
"/xpack/waf/log": {},
|
||||||
|
"/xpack/waf/block": {},
|
||||||
|
"/xpack/monitor/dashboard": {},
|
||||||
|
"/xpack/monitor/setting": {},
|
||||||
|
"/xpack/monitor/rank": {},
|
||||||
|
"/xpack/monitor/log": {},
|
||||||
|
"/xpack/tamper": {},
|
||||||
|
"/xpack/gpu": {},
|
||||||
|
"/xpack/alert/dashboard": {},
|
||||||
|
"/xpack/alert/log": {},
|
||||||
|
"/xpack/alert/setting": {},
|
||||||
|
"/xpack/setting": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
var DynamicRoutes = []string{
|
||||||
|
`^/containers/composeDetail/[^/]+$`,
|
||||||
|
`^/databases/mysql/setting/[^/]+/[^/]+$`,
|
||||||
|
`^/databases/postgresql/setting/[^/]+/[^/]+$`,
|
||||||
|
`^/websites/[^/]+/config/[^/]+$`,
|
||||||
|
}
|
||||||
|
|
||||||
var CertStore atomic.Value
|
var CertStore atomic.Value
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/1Panel-dev/1Panel/core/app/service"
|
||||||
|
"github.com/1Panel-dev/1Panel/core/cmd/server/res"
|
||||||
|
"github.com/1Panel-dev/1Panel/core/constant"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/core/cmd/server/docs"
|
"github.com/1Panel-dev/1Panel/core/cmd/server/docs"
|
||||||
"github.com/1Panel-dev/1Panel/core/cmd/server/web"
|
"github.com/1Panel-dev/1Panel/core/cmd/server/web"
|
||||||
@ -21,8 +28,91 @@ var (
|
|||||||
Router *gin.Engine
|
Router *gin.Engine
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func toIndexHtml(c *gin.Context) {
|
||||||
|
c.Writer.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
c.Writer.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = c.Writer.Write(web.IndexByte)
|
||||||
|
c.Writer.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func isEntrancePath(c *gin.Context) bool {
|
||||||
|
entrance := service.NewIAuthService().GetSecurityEntrance()
|
||||||
|
if entrance != "" && strings.TrimSuffix(c.Request.URL.Path, "/") == "/"+entrance {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkEntrance(c *gin.Context) bool {
|
||||||
|
authService := service.NewIAuthService()
|
||||||
|
entrance := authService.GetSecurityEntrance()
|
||||||
|
if entrance == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
cookieValue, err := c.Cookie("SecurityEntrance")
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
entranceValue, err := base64.StdEncoding.DecodeString(cookieValue)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return string(entranceValue) == entrance
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleNoRoute(c *gin.Context) {
|
||||||
|
resPage, err := service.NewIAuthService().GetResponsePage()
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusInternalServerError, "Internal Server Error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resPage == "444" {
|
||||||
|
c.String(444, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file := fmt.Sprintf("html/%s.html", resPage)
|
||||||
|
data, err := res.ErrorMsg.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusInternalServerError, "Internal Server Error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
statusCode, err := strconv.Atoi(resPage)
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusInternalServerError, "Internal Server Error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Data(statusCode, "text/html; charset=utf-8", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFrontendPath(c *gin.Context) bool {
|
||||||
|
reqUri := strings.TrimSuffix(c.Request.URL.Path, "/")
|
||||||
|
if _, ok := constant.WebUrlMap[reqUri]; ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, route := range constant.DynamicRoutes {
|
||||||
|
if match, _ := regexp.MatchString(route, reqUri); match {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkFrontendPath(c *gin.Context) bool {
|
||||||
|
if !isFrontendPath(c) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
authService := service.NewIAuthService()
|
||||||
|
if authService.GetSecurityEntrance() != "" {
|
||||||
|
return authService.IsLogin(c)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func setWebStatic(rootRouter *gin.RouterGroup) {
|
func setWebStatic(rootRouter *gin.RouterGroup) {
|
||||||
rootRouter.StaticFS("/public", http.FS(web.Favicon))
|
rootRouter.StaticFS("/public", http.FS(web.Favicon))
|
||||||
|
rootRouter.StaticFS("/favicon.ico", http.FS(web.Favicon))
|
||||||
rootRouter.Static("/api/v2/images", "./uploads")
|
rootRouter.Static("/api/v2/images", "./uploads")
|
||||||
rootRouter.Use(func(c *gin.Context) {
|
rootRouter.Use(func(c *gin.Context) {
|
||||||
c.Next()
|
c.Next()
|
||||||
@ -32,7 +122,23 @@ func setWebStatic(rootRouter *gin.RouterGroup) {
|
|||||||
staticServer := http.FileServer(http.FS(web.Assets))
|
staticServer := http.FileServer(http.FS(web.Assets))
|
||||||
staticServer.ServeHTTP(c.Writer, c.Request)
|
staticServer.ServeHTTP(c.Writer, c.Request)
|
||||||
})
|
})
|
||||||
|
authService := service.NewIAuthService()
|
||||||
|
entrance := authService.GetSecurityEntrance()
|
||||||
|
if entrance != "" {
|
||||||
|
rootRouter.GET("/"+entrance, func(c *gin.Context) {
|
||||||
|
entrance = authService.GetSecurityEntrance()
|
||||||
|
if entrance == "" {
|
||||||
|
handleNoRoute(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
toIndexHtml(c)
|
||||||
|
})
|
||||||
|
}
|
||||||
rootRouter.GET("/", func(c *gin.Context) {
|
rootRouter.GET("/", func(c *gin.Context) {
|
||||||
|
if !checkEntrance(c) {
|
||||||
|
handleNoRoute(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
staticServer := http.FileServer(http.FS(web.IndexHtml))
|
staticServer := http.FileServer(http.FS(web.IndexHtml))
|
||||||
staticServer.ServeHTTP(c.Writer, c.Request)
|
staticServer.ServeHTTP(c.Writer, c.Request)
|
||||||
})
|
})
|
||||||
@ -69,10 +175,15 @@ func Routers() *gin.Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Router.NoRoute(func(c *gin.Context) {
|
Router.NoRoute(func(c *gin.Context) {
|
||||||
c.Writer.WriteHeader(http.StatusOK)
|
if checkFrontendPath(c) {
|
||||||
_, _ = c.Writer.Write(web.IndexByte)
|
toIndexHtml(c)
|
||||||
c.Writer.Header().Add("Accept", "text/html")
|
return
|
||||||
c.Writer.Flush()
|
}
|
||||||
|
if isEntrancePath(c) {
|
||||||
|
toIndexHtml(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handleNoRoute(c)
|
||||||
})
|
})
|
||||||
|
|
||||||
return Router
|
return Router
|
||||||
|
@ -53,22 +53,6 @@ class RequestHttp {
|
|||||||
});
|
});
|
||||||
return Promise.reject(data);
|
return Promise.reject(data);
|
||||||
}
|
}
|
||||||
if (data.code == ResultEnum.NOTFOUND) {
|
|
||||||
globalStore.errStatus = 'err-found';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (data.code == ResultEnum.ERRIP) {
|
|
||||||
globalStore.errStatus = 'err-ip';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (data.code == ResultEnum.ERRDOMAIN) {
|
|
||||||
globalStore.errStatus = 'err-domain';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (data.code == ResultEnum.UNSAFETY) {
|
|
||||||
globalStore.errStatus = 'err-unsafe';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (data.code == ResultEnum.EXPIRED) {
|
if (data.code == ResultEnum.EXPIRED) {
|
||||||
router.push({ name: 'Expired' });
|
router.push({ name: 'Expired' });
|
||||||
return;
|
return;
|
||||||
@ -106,27 +90,6 @@ class RequestHttp {
|
|||||||
if (error.message.indexOf('timeout') !== -1) MsgError('请求超时!请您稍后重试');
|
if (error.message.indexOf('timeout') !== -1) MsgError('请求超时!请您稍后重试');
|
||||||
if (response) {
|
if (response) {
|
||||||
switch (response.status) {
|
switch (response.status) {
|
||||||
case 310:
|
|
||||||
globalStore.errStatus = 'err-ip';
|
|
||||||
router.push({
|
|
||||||
name: 'entrance',
|
|
||||||
params: { code: globalStore.entrance },
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
case 311:
|
|
||||||
globalStore.errStatus = 'err-domain';
|
|
||||||
router.push({
|
|
||||||
name: 'entrance',
|
|
||||||
params: { code: globalStore.entrance },
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
case 312:
|
|
||||||
globalStore.errStatus = 'err-entrance';
|
|
||||||
router.push({
|
|
||||||
name: 'entrance',
|
|
||||||
params: { code: globalStore.entrance },
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
case 313:
|
case 313:
|
||||||
router.push({ name: 'Expired' });
|
router.push({ name: 'Expired' });
|
||||||
return;
|
return;
|
||||||
|
@ -1638,6 +1638,8 @@ const message = {
|
|||||||
error404: 'Not Found',
|
error404: 'Not Found',
|
||||||
error408: 'Request Timeout',
|
error408: 'Request Timeout',
|
||||||
error416: 'Range Not Satisfiable',
|
error416: 'Range Not Satisfiable',
|
||||||
|
error444: 'Connection Closed',
|
||||||
|
error500: 'Internal Server Error',
|
||||||
|
|
||||||
https: 'Setting up HTTPS protocol access for the panel can enhance the security of panel access.',
|
https: 'Setting up HTTPS protocol access for the panel can enhance the security of panel access.',
|
||||||
certType: 'Certificate type',
|
certType: 'Certificate type',
|
||||||
|
@ -1606,6 +1606,8 @@ const message = {
|
|||||||
error404: '未找到',
|
error404: '未找到',
|
||||||
error408: '請求超時',
|
error408: '請求超時',
|
||||||
error416: '無效請求',
|
error416: '無效請求',
|
||||||
|
error444: '連線已關閉',
|
||||||
|
error500: '內部伺服器錯誤',
|
||||||
|
|
||||||
https: '為面板設置 https 協議訪問,提升面板訪問安全性',
|
https: '為面板設置 https 協議訪問,提升面板訪問安全性',
|
||||||
certType: '證書類型',
|
certType: '證書類型',
|
||||||
|
@ -1604,6 +1604,8 @@ const message = {
|
|||||||
error404: '未找到',
|
error404: '未找到',
|
||||||
error408: '请求超时',
|
error408: '请求超时',
|
||||||
error416: '无效请求',
|
error416: '无效请求',
|
||||||
|
error444: '连接被关闭',
|
||||||
|
error500: '内部错误',
|
||||||
|
|
||||||
https: '为面板设置 https 协议访问,提升面板访问安全性',
|
https: '为面板设置 https 协议访问,提升面板访问安全性',
|
||||||
certType: '证书类型',
|
certType: '证书类型',
|
||||||
|
@ -72,12 +72,6 @@ export const routes: RouteRecordRaw[] = [
|
|||||||
key: 'login',
|
key: 'login',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/:code?',
|
|
||||||
name: 'entrance',
|
|
||||||
component: () => import('@/views/login/entrance/index.vue'),
|
|
||||||
props: true,
|
|
||||||
},
|
|
||||||
...routerArray,
|
...routerArray,
|
||||||
{
|
{
|
||||||
path: '/:pathMatch(.*)',
|
path: '/:pathMatch(.*)',
|
||||||
|
@ -1,186 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div v-if="!loading">
|
|
||||||
<div class="login-background" v-if="errStatus === ''">
|
|
||||||
<div class="login-wrapper">
|
|
||||||
<div :class="screenWidth > 1110 ? 'left inline-block' : ''">
|
|
||||||
<div class="login-title">
|
|
||||||
<span>{{ globalStore.themeConfig.title || $t('setting.description') }}</span>
|
|
||||||
</div>
|
|
||||||
<img src="@/assets/images/1panel-login.png" alt="" v-if="screenWidth > 1110" />
|
|
||||||
</div>
|
|
||||||
<div :class="screenWidth > 1110 ? 'right inline-block' : ''">
|
|
||||||
<div class="login-container">
|
|
||||||
<LoginForm ref="loginRef"></LoginForm>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else>
|
|
||||||
<div v-if="errStatus === 'err-unsafe'">
|
|
||||||
<UnSafe />
|
|
||||||
</div>
|
|
||||||
<div v-if="errStatus === 'err-ip'">
|
|
||||||
<ErrIP />
|
|
||||||
</div>
|
|
||||||
<div v-if="errStatus === 'err-domain'">
|
|
||||||
<ErrDomain />
|
|
||||||
</div>
|
|
||||||
<div v-if="errStatus.indexOf('code-') !== -1">
|
|
||||||
<ErrCode :code="errStatus.replaceAll('code-', '')" />
|
|
||||||
</div>
|
|
||||||
<div v-if="errStatus === 'err-found'">
|
|
||||||
<ErrFound />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts" name="login">
|
|
||||||
import { checkIsSafety } from '@/api/modules/auth';
|
|
||||||
import LoginForm from '../components/login-form.vue';
|
|
||||||
import UnSafe from '@/components/error-message/unsafe.vue';
|
|
||||||
import ErrIP from '@/components/error-message/err_ip.vue';
|
|
||||||
import ErrCode from '@/components/error-message/error_code.vue';
|
|
||||||
import ErrDomain from '@/components/error-message/err_domain.vue';
|
|
||||||
import ErrFound from '@/components/error-message/404.vue';
|
|
||||||
import { ref, onMounted, watch } from 'vue';
|
|
||||||
import { GlobalStore } from '@/store';
|
|
||||||
import { getXpackSettingForTheme } from '@/utils/xpack';
|
|
||||||
const globalStore = GlobalStore();
|
|
||||||
|
|
||||||
const screenWidth = ref(null);
|
|
||||||
const errStatus = ref('');
|
|
||||||
const loading = ref();
|
|
||||||
|
|
||||||
const mySafetyCode = defineProps({
|
|
||||||
code: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
watch(
|
|
||||||
() => globalStore.errStatus,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal?.startsWith('err-') || newVal?.startsWith('code-')) {
|
|
||||||
errStatus.value = newVal;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const getStatus = async () => {
|
|
||||||
let info = globalStore.errStatus;
|
|
||||||
if (info?.startsWith('err-') || info?.startsWith('code-')) {
|
|
||||||
errStatus.value = info;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let code = mySafetyCode.code;
|
|
||||||
globalStore.entrance = code;
|
|
||||||
loading.value = true;
|
|
||||||
await checkIsSafety(code)
|
|
||||||
.then(() => {
|
|
||||||
loading.value = false;
|
|
||||||
getXpackSettingForTheme();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
loading.value = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
globalStore.isOnRestart = false;
|
|
||||||
getStatus();
|
|
||||||
screenWidth.value = document.body.clientWidth;
|
|
||||||
window.onresize = () => {
|
|
||||||
return (() => {
|
|
||||||
screenWidth.value = document.body.clientWidth;
|
|
||||||
})();
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
@mixin login-center {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-background {
|
|
||||||
height: 100vh;
|
|
||||||
background: url(@/assets/images/1panel-login-bg.png) no-repeat,
|
|
||||||
radial-gradient(153.25% 257.2% at 118.99% 181.67%, rgba(50, 132, 255, 0.2) 0%, rgba(82, 120, 255, 0) 100%)
|
|
||||||
/* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */,
|
|
||||||
radial-gradient(123.54% 204.83% at 25.87% 195.17%, rgba(111, 76, 253, 0.15) 0%, rgba(122, 76, 253, 0) 78.85%)
|
|
||||||
/* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */,
|
|
||||||
linear-gradient(0deg, rgba(0, 94, 235, 0.03), rgba(0, 94, 235, 0.03)),
|
|
||||||
radial-gradient(109.58% 109.58% at 31.53% -36.58%, rgba(0, 94, 235, 0.3) 0%, rgba(0, 94, 235, 0) 100%)
|
|
||||||
/* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */,
|
|
||||||
rgba(0, 57, 142, 0.05);
|
|
||||||
|
|
||||||
.login-wrapper {
|
|
||||||
padding-top: 8%;
|
|
||||||
width: 80%;
|
|
||||||
margin: 0 auto;
|
|
||||||
// @media only screen and (max-width: 1440px) {
|
|
||||||
// width: 100%;
|
|
||||||
// padding-top: 6%;
|
|
||||||
// }
|
|
||||||
.left {
|
|
||||||
vertical-align: middle;
|
|
||||||
text-align: right;
|
|
||||||
width: 60%;
|
|
||||||
img {
|
|
||||||
object-fit: contain;
|
|
||||||
width: 100%;
|
|
||||||
@media only screen and (min-width: 1440px) {
|
|
||||||
width: 85%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.right {
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 40%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-title {
|
|
||||||
text-align: right;
|
|
||||||
margin-right: 10%;
|
|
||||||
span:first-child {
|
|
||||||
color: #005eeb;
|
|
||||||
font-size: 40px;
|
|
||||||
font-family: pingFangSC-Regular;
|
|
||||||
font-weight: 600;
|
|
||||||
@media only screen and (max-width: 768px) {
|
|
||||||
font-size: 35px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 1110px) {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
font-size: 35px;
|
|
||||||
text-align: center;
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.login-container {
|
|
||||||
margin-top: 40px;
|
|
||||||
padding: 40px 0;
|
|
||||||
width: 390px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background-color: rgba(255, 255, 255, 0.55);
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: 2px 4px 22px rgba(0, 94, 235, 0.2);
|
|
||||||
@media only screen and (max-width: 1440px) {
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 1110px) {
|
|
||||||
margin: 60px auto 0;
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 768px) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -63,6 +63,14 @@ const options = [
|
|||||||
value: '416',
|
value: '416',
|
||||||
label: '416 - ' + i18n.global.t('setting.error416'),
|
label: '416 - ' + i18n.global.t('setting.error416'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: '444',
|
||||||
|
label: '444 - ' + i18n.global.t('setting.error444'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '500',
|
||||||
|
label: '500 - ' + i18n.global.t('setting.error500'),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
interface DialogProps {
|
interface DialogProps {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user