auth
This commit is contained in:
parent
10d56d13da
commit
817e8edb28
4
.gitignore
vendored
4
.gitignore
vendored
@ -62,4 +62,6 @@ src/proxies/*
|
|||||||
src/rules/*
|
src/rules/*
|
||||||
acl4ssr_repo
|
acl4ssr_repo
|
||||||
lufxy.yaml
|
lufxy.yaml
|
||||||
result.yaml
|
desult.yaml
|
||||||
|
src/passwd
|
||||||
|
passwd
|
||||||
@ -1,13 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"proxyrules/src/service"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -43,7 +43,6 @@ const htmlTemplate = `
|
|||||||
color: green;
|
color: green;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
/* 设置页面的样式 */
|
|
||||||
body, html {
|
body, html {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -51,8 +50,6 @@ const htmlTemplate = `
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 背景容器 */
|
|
||||||
.background {
|
.background {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -62,53 +59,44 @@ const htmlTemplate = `
|
|||||||
background: url('static/background.jpg') no-repeat center center;
|
background: url('static/background.jpg') no-repeat center center;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 半透明白色覆盖层 */
|
|
||||||
.overlay {
|
.overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: rgba(255, 255, 255, 0.5); /* 半透明白色 */
|
background: rgba(255, 255, 255, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 页面内容 */
|
|
||||||
.content {
|
.content {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1; /* 确保内容在覆盖层之上 */
|
z-index: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 2.5em;
|
font-size: 2.5em;
|
||||||
color: black; /* 内容颜色 */
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
color: black; /* 内容颜色 */
|
color: black;
|
||||||
}
|
}
|
||||||
.form-container {
|
.form-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: 600px; /* 表单容器的最大宽度 */
|
max-width: 600px;
|
||||||
margin: 50px auto; /* 居中 */
|
margin: 50px auto;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
background: rgba(255, 255, 255, 0.7); /* 半透明白色背景 */
|
background: rgba(255, 255, 255, 0.7);
|
||||||
border-radius: 15px; /* 圆角 */
|
border-radius: 15px;
|
||||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); /* 添加阴影 */
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="background"></div>
|
<div class="background"></div>
|
||||||
|
|
||||||
<!-- 覆盖层 -->
|
|
||||||
<div class="overlay"></div>
|
<div class="overlay"></div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
|
||||||
<h1>Welcome to 404 Clash Config Site !~~</h1>
|
<h1>Welcome to 404 Clash Config Site !~~</h1>
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<form method="POST" action="/update">
|
<form method="POST" action="/update">
|
||||||
@ -165,10 +153,11 @@ const htmlTemplate = `
|
|||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`
|
`
|
||||||
|
const (
|
||||||
// 文件路径
|
defaultFilePath = "src/proxies/default.list"
|
||||||
const defaultFilePath = "src/proxies/default.list"
|
clashConfigPath = "lufxy.yaml"
|
||||||
const clashConfigPath = "lufxy.yaml"
|
credentialsFile = "src/passwd" // 用户名密码文件路径
|
||||||
|
)
|
||||||
|
|
||||||
// 读取默认列表文件
|
// 读取默认列表文件
|
||||||
func readDefaultList() ([]string, error) {
|
func readDefaultList() ([]string, error) {
|
||||||
@ -177,7 +166,6 @@ func readDefaultList() ([]string, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
lines := strings.Split(string(content), "\n")
|
lines := strings.Split(string(content), "\n")
|
||||||
// 去除空行
|
|
||||||
var result []string
|
var result []string
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
trimmed := strings.TrimSpace(line)
|
trimmed := strings.TrimSpace(line)
|
||||||
@ -203,16 +191,56 @@ func readClashConfig() (string, error) {
|
|||||||
return string(content), nil
|
return string(content), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从文件加载用户名和密码
|
||||||
|
func loadCredentials(filePath string) (map[string]string, error) {
|
||||||
|
credentials := make(map[string]string)
|
||||||
|
|
||||||
|
// 打开文件
|
||||||
|
file, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to open credentials file: %v", err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// 逐行读取用户名和密码
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := strings.TrimSpace(scanner.Text())
|
||||||
|
if line == "" || strings.HasPrefix(line, "#") { // 忽略空行和注释
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
parts := strings.SplitN(line, ":", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return nil, fmt.Errorf("invalid credentials format: %s", line)
|
||||||
|
}
|
||||||
|
username := strings.TrimSpace(parts[0])
|
||||||
|
password := strings.TrimSpace(parts[1])
|
||||||
|
credentials[username] = password
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading credentials file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return credentials, nil
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
service.GenerateConfig()
|
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
r.Static("/static", "./static") // 将 static 目录映射到 /static 路径
|
r.Static("/static", "./static") // 将 static 目录映射到 /static 路径
|
||||||
|
|
||||||
// 加载 HTML 模版
|
|
||||||
r.SetHTMLTemplate(template.Must(template.New("index").Parse(htmlTemplate)))
|
r.SetHTMLTemplate(template.Must(template.New("index").Parse(htmlTemplate)))
|
||||||
|
|
||||||
|
// 加载用户名和密码
|
||||||
|
credentials, err := loadCredentials(credentialsFile)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("Failed to load credentials: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用从文件加载的用户名和密码
|
||||||
|
authorized := r.Group("/", gin.BasicAuth(credentials))
|
||||||
|
|
||||||
// 显示文件内容和操作界面
|
// 显示文件内容和操作界面
|
||||||
r.GET("/", func(c *gin.Context) {
|
authorized.GET("/", func(c *gin.Context) {
|
||||||
lines, err := readDefaultList()
|
lines, err := readDefaultList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusInternalServerError, fmt.Sprintf("Error reading file: %v", err))
|
c.String(http.StatusInternalServerError, fmt.Sprintf("Error reading file: %v", err))
|
||||||
@ -222,7 +250,7 @@ func main() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 提交更新后的文件内容
|
// 提交更新后的文件内容
|
||||||
r.POST("/update", func(c *gin.Context) {
|
authorized.POST("/update", func(c *gin.Context) {
|
||||||
formLines := c.PostFormArray("lines")
|
formLines := c.PostFormArray("lines")
|
||||||
if err := writeDefaultList(formLines); err != nil {
|
if err := writeDefaultList(formLines); err != nil {
|
||||||
c.String(http.StatusInternalServerError, fmt.Sprintf("Error writing file: %v", err))
|
c.String(http.StatusInternalServerError, fmt.Sprintf("Error writing file: %v", err))
|
||||||
@ -232,7 +260,7 @@ func main() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 下载 Clash 配置
|
// 下载 Clash 配置
|
||||||
r.GET("/download", func(c *gin.Context) {
|
authorized.GET("/download", func(c *gin.Context) {
|
||||||
if _, err := os.Stat(clashConfigPath); os.IsNotExist(err) {
|
if _, err := os.Stat(clashConfigPath); os.IsNotExist(err) {
|
||||||
c.String(http.StatusNotFound, "Clash configuration file not found")
|
c.String(http.StatusNotFound, "Clash configuration file not found")
|
||||||
return
|
return
|
||||||
@ -241,7 +269,7 @@ func main() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 将 Clash 配置放入剪贴板
|
// 将 Clash 配置放入剪贴板
|
||||||
r.GET("/clipboard", func(c *gin.Context) {
|
authorized.GET("/clipboard", func(c *gin.Context) {
|
||||||
config, err := readClashConfig()
|
config, err := readClashConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusInternalServerError, fmt.Sprintf("Error reading Clash config: %v", err))
|
c.String(http.StatusInternalServerError, fmt.Sprintf("Error reading Clash config: %v", err))
|
||||||
@ -250,6 +278,5 @@ func main() {
|
|||||||
c.JSON(http.StatusOK, gin.H{"content": config})
|
c.JSON(http.StatusOK, gin.H{"content": config})
|
||||||
})
|
})
|
||||||
|
|
||||||
// 启动服务
|
|
||||||
r.Run(":8080") // 在 http://localhost:8080 提供服务
|
r.Run(":8080") // 在 http://localhost:8080 提供服务
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user