mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-08 00:26:37 +08:00
[优化] 添加基础鉴权配置支持,包括用户名和密码
This commit is contained in:
@@ -26,6 +26,9 @@ type ProxyRoute struct {
|
|||||||
CustomHeaders string `json:"custom_headers" gorm:"type:text;not null;default:'[]'"`
|
CustomHeaders string `json:"custom_headers" gorm:"type:text;not null;default:'[]'"`
|
||||||
PoWEnabled bool `json:"pow_enabled" gorm:"column:pow_enabled;not null;default:false"`
|
PoWEnabled bool `json:"pow_enabled" gorm:"column:pow_enabled;not null;default:false"`
|
||||||
PoWConfig string `json:"pow_config" gorm:"column:pow_config;type:text;not null;default:'{}'"`
|
PoWConfig string `json:"pow_config" gorm:"column:pow_config;type:text;not null;default:'{}'"`
|
||||||
|
BasicAuthEnabled bool `json:"basic_auth_enabled" gorm:"not null;default:false"`
|
||||||
|
BasicAuthUsername string `json:"basic_auth_username" gorm:"size:255;not null;default:''"`
|
||||||
|
BasicAuthPassword string `json:"basic_auth_password" gorm:"size:255;not null;default:''"`
|
||||||
Remark string `json:"remark" gorm:"size:255"`
|
Remark string `json:"remark" gorm:"size:255"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
@@ -80,6 +83,9 @@ func (route *ProxyRoute) Update() error {
|
|||||||
"custom_headers": route.CustomHeaders,
|
"custom_headers": route.CustomHeaders,
|
||||||
"pow_enabled": route.PoWEnabled,
|
"pow_enabled": route.PoWEnabled,
|
||||||
"pow_config": route.PoWConfig,
|
"pow_config": route.PoWConfig,
|
||||||
|
"basic_auth_enabled": route.BasicAuthEnabled,
|
||||||
|
"basic_auth_username": route.BasicAuthUsername,
|
||||||
|
"basic_auth_password": route.BasicAuthPassword,
|
||||||
"remark": route.Remark,
|
"remark": route.Remark,
|
||||||
}).Error
|
}).Error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
@@ -929,7 +930,7 @@ func renderRouteConfig(routes []*model.ProxyRoute, cfg openRestyConfigSnapshot)
|
|||||||
builder.WriteString(renderNamedUpstreamBlock(upstreamConfig))
|
builder.WriteString(renderNamedUpstreamBlock(upstreamConfig))
|
||||||
}
|
}
|
||||||
if !route.EnableHTTPS {
|
if !route.EnableHTTPS {
|
||||||
builder.WriteString(renderHTTPProxyServer(serverNames, route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, cfg))
|
builder.WriteString(renderHTTPProxyServer(serverNames, route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
certIDs, err := decodeStoredCertIDs(route.CertIDs, route.CertID)
|
certIDs, err := decodeStoredCertIDs(route.CertIDs, route.CertID)
|
||||||
@@ -990,7 +991,7 @@ func renderRouteConfig(routes []*model.ProxyRoute, cfg openRestyConfigSnapshot)
|
|||||||
|
|
||||||
if route.RedirectHTTP {
|
if route.RedirectHTTP {
|
||||||
if len(httpOnlyDomains) > 0 {
|
if len(httpOnlyDomains) > 0 {
|
||||||
builder.WriteString(renderHTTPProxyServer(renderServerNames(httpOnlyDomains), route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, cfg))
|
builder.WriteString(renderHTTPProxyServer(renderServerNames(httpOnlyDomains), route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
|
||||||
}
|
}
|
||||||
for _, certID := range certIDs {
|
for _, certID := range certIDs {
|
||||||
assignedDomains := domainsByCertID[certID]
|
assignedDomains := domainsByCertID[certID]
|
||||||
@@ -1000,14 +1001,14 @@ func renderRouteConfig(routes []*model.ProxyRoute, cfg openRestyConfigSnapshot)
|
|||||||
builder.WriteString(renderHTTPRedirectServer(renderServerNames(assignedDomains)))
|
builder.WriteString(renderHTTPRedirectServer(renderServerNames(assignedDomains)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
builder.WriteString(renderHTTPProxyServer(serverNames, route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, cfg))
|
builder.WriteString(renderHTTPProxyServer(serverNames, route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
|
||||||
}
|
}
|
||||||
for _, certID := range certIDs {
|
for _, certID := range certIDs {
|
||||||
assignedDomains := domainsByCertID[certID]
|
assignedDomains := domainsByCertID[certID]
|
||||||
if len(assignedDomains) == 0 {
|
if len(assignedDomains) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
builder.WriteString(renderHTTPSServer(renderServerNames(assignedDomains), route.OriginURL, route.OriginHost, certID, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, cfg))
|
builder.WriteString(renderHTTPSServer(renderServerNames(assignedDomains), route.OriginURL, route.OriginHost, certID, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return builder.String(), dedupeSupportFiles(supportFiles), nil
|
return builder.String(), dedupeSupportFiles(supportFiles), nil
|
||||||
@@ -1123,6 +1124,22 @@ func renderPowAccessBlock(powEnabled bool) string {
|
|||||||
return fmt.Sprintf(" access_by_lua_file %s/pow/check.lua;\n", nginxLuaDirPlaceholder)
|
return fmt.Sprintf(" access_by_lua_file %s/pow/check.lua;\n", nginxLuaDirPlaceholder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func renderBasicAuthBlock(enabled bool, username, password string) string {
|
||||||
|
if !enabled || username == "" || password == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
credentials := username + ":" + password
|
||||||
|
encoded := base64.StdEncoding.EncodeToString([]byte(credentials))
|
||||||
|
return fmt.Sprintf(` rewrite_by_lua_block {
|
||||||
|
local auth = ngx.var.http_authorization
|
||||||
|
if auth ~= "Basic %s" then
|
||||||
|
ngx.header["WWW-Authenticate"] = 'Basic realm="Restricted"'
|
||||||
|
return ngx.exit(401)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, encoded)
|
||||||
|
}
|
||||||
|
|
||||||
func renderPowLocationBlocks(powEnabled bool) string {
|
func renderPowLocationBlocks(powEnabled bool) string {
|
||||||
if !powEnabled {
|
if !powEnabled {
|
||||||
return ""
|
return ""
|
||||||
@@ -1250,21 +1267,21 @@ func nextVersionNumber(now time.Time) (string, error) {
|
|||||||
return fmt.Sprintf("%s-%03d", prefix, count+1), nil
|
return fmt.Sprintf("%s-%03d", prefix, count+1), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderHTTPProxyServer(serverNames string, originURL string, originHost string, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, cfg openRestyConfigSnapshot) string {
|
func renderHTTPProxyServer(serverNames string, originURL string, originHost string, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, basicAuthEnabled bool, basicAuthUsername string, basicAuthPassword string, cfg openRestyConfigSnapshot) string {
|
||||||
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n%s location / {\n%s%s%s%s%s }\n%s}\n\n", serverNames, renderPowLocationBlocks(powEnabled), renderPowAccessBlock(powEnabled), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n%s location / {\n%s%s%s%s%s%s }\n%s}\n\n", serverNames, renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthEnabled, basicAuthUsername, basicAuthPassword), renderPowAccessBlock(powEnabled), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderHTTPRedirectServer(serverNames string) string {
|
func renderHTTPRedirectServer(serverNames string) string {
|
||||||
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n\n return 301 https://$host$request_uri;\n}\n\n", serverNames)
|
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n\n return 301 https://$host$request_uri;\n}\n\n", serverNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderHTTPSServer(serverNames string, originURL string, originHost string, certificateID uint, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, cfg openRestyConfigSnapshot) string {
|
func renderHTTPSServer(serverNames string, originURL string, originHost string, certificateID uint, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, basicAuthEnabled bool, basicAuthUsername string, basicAuthPassword string, cfg openRestyConfigSnapshot) string {
|
||||||
certPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateCertFileName(certificateID))
|
certPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateCertFileName(certificateID))
|
||||||
keyPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateKeyFileName(certificateID))
|
keyPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateKeyFileName(certificateID))
|
||||||
return fmt.Sprintf("server {\n listen 443 ssl;\n http2 on;\n server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n%s location / {\n%s%s%s%s%s }\n%s}\n\n", serverNames, certPath, keyPath, renderPowLocationBlocks(powEnabled), renderPowAccessBlock(powEnabled), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
return fmt.Sprintf("server {\n listen 443 ssl;\n http2 on;\n server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n%s location / {\n%s%s%s%s%s%s }\n%s}\n\n", serverNames, certPath, keyPath, renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthEnabled, basicAuthUsername, basicAuthPassword), renderPowAccessBlock(powEnabled), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderHTTPSServerWithCertificates(serverNames string, originURL string, originHost string, certificateIDs []uint, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, cfg openRestyConfigSnapshot) string {
|
func renderHTTPSServerWithCertificates(serverNames string, originURL string, originHost string, certificateIDs []uint, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, basicAuthEnabled bool, basicAuthUsername string, basicAuthPassword string, cfg openRestyConfigSnapshot) string {
|
||||||
var certificateBlock strings.Builder
|
var certificateBlock strings.Builder
|
||||||
for _, certificateID := range certificateIDs {
|
for _, certificateID := range certificateIDs {
|
||||||
certPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateCertFileName(certificateID))
|
certPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateCertFileName(certificateID))
|
||||||
@@ -1272,7 +1289,7 @@ func renderHTTPSServerWithCertificates(serverNames string, originURL string, ori
|
|||||||
certificateBlock.WriteString(fmt.Sprintf(" ssl_certificate %s;\n", certPath))
|
certificateBlock.WriteString(fmt.Sprintf(" ssl_certificate %s;\n", certPath))
|
||||||
certificateBlock.WriteString(fmt.Sprintf(" ssl_certificate_key %s;\n", keyPath))
|
certificateBlock.WriteString(fmt.Sprintf(" ssl_certificate_key %s;\n", keyPath))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("server {\n listen 443 ssl;\n http2 on;\n server_name %s;\n%s\n location / {\n%s%s%s%s }\n}\n\n", serverNames, certificateBlock.String(), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig))
|
return fmt.Sprintf("server {\n listen 443 ssl;\n http2 on;\n server_name %s;\n%s%s\n location / {\n%s%s%s%s%s%s }\n%s}\n\n", serverNames, certificateBlock.String(), renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthEnabled, basicAuthUsername, basicAuthPassword), renderPowAccessBlock(powEnabled), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderServerNames(domains []string) string {
|
func renderServerNames(domains []string) string {
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ type ProxyRouteInput struct {
|
|||||||
CustomHeaders []ProxyRouteCustomHeaderInput `json:"custom_headers"`
|
CustomHeaders []ProxyRouteCustomHeaderInput `json:"custom_headers"`
|
||||||
PoWEnabled bool `json:"pow_enabled"`
|
PoWEnabled bool `json:"pow_enabled"`
|
||||||
PoWConfig string `json:"pow_config"`
|
PoWConfig string `json:"pow_config"`
|
||||||
|
BasicAuthEnabled bool `json:"basic_auth_enabled"`
|
||||||
|
BasicAuthUsername string `json:"basic_auth_username"`
|
||||||
|
BasicAuthPassword string `json:"basic_auth_password"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +91,9 @@ type ProxyRouteView struct {
|
|||||||
CustomHeaderList []ProxyRouteCustomHeaderInput `json:"custom_header_list"`
|
CustomHeaderList []ProxyRouteCustomHeaderInput `json:"custom_header_list"`
|
||||||
PoWEnabled bool `json:"pow_enabled"`
|
PoWEnabled bool `json:"pow_enabled"`
|
||||||
PoWConfig *ProxyRoutePoWConfig `json:"pow_config"`
|
PoWConfig *ProxyRoutePoWConfig `json:"pow_config"`
|
||||||
|
BasicAuthEnabled bool `json:"basic_auth_enabled"`
|
||||||
|
BasicAuthUsername string `json:"basic_auth_username"`
|
||||||
|
BasicAuthPassword string `json:"basic_auth_password"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
@@ -259,6 +265,17 @@ func buildProxyRoute(route *model.ProxyRoute, input ProxyRouteInput) (*model.Pro
|
|||||||
return nil, errors.New("redirect_http requires enable_https")
|
return nil, errors.New("redirect_http requires enable_https")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if input.BasicAuthEnabled {
|
||||||
|
input.BasicAuthUsername = strings.TrimSpace(input.BasicAuthUsername)
|
||||||
|
input.BasicAuthPassword = strings.TrimSpace(input.BasicAuthPassword)
|
||||||
|
if input.BasicAuthUsername == "" || input.BasicAuthPassword == "" {
|
||||||
|
return nil, errors.New("basic_auth_username and basic_auth_password cannot be empty when basic auth is enabled")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
input.BasicAuthUsername = ""
|
||||||
|
input.BasicAuthPassword = ""
|
||||||
|
}
|
||||||
|
|
||||||
if route == nil {
|
if route == nil {
|
||||||
route = &model.ProxyRoute{}
|
route = &model.ProxyRoute{}
|
||||||
}
|
}
|
||||||
@@ -284,6 +301,9 @@ func buildProxyRoute(route *model.ProxyRoute, input ProxyRouteInput) (*model.Pro
|
|||||||
route.CustomHeaders = string(customHeadersJSON)
|
route.CustomHeaders = string(customHeadersJSON)
|
||||||
route.PoWEnabled = input.PoWEnabled
|
route.PoWEnabled = input.PoWEnabled
|
||||||
route.PoWConfig = string(powConfigJSON)
|
route.PoWConfig = string(powConfigJSON)
|
||||||
|
route.BasicAuthEnabled = input.BasicAuthEnabled
|
||||||
|
route.BasicAuthUsername = input.BasicAuthUsername
|
||||||
|
route.BasicAuthPassword = input.BasicAuthPassword
|
||||||
route.Remark = remark
|
route.Remark = remark
|
||||||
return route, nil
|
return route, nil
|
||||||
}
|
}
|
||||||
@@ -366,6 +386,9 @@ func buildProxyRouteView(route *model.ProxyRoute) (*ProxyRouteView, error) {
|
|||||||
CustomHeaderList: customHeaders,
|
CustomHeaderList: customHeaders,
|
||||||
PoWEnabled: route.PoWEnabled,
|
PoWEnabled: route.PoWEnabled,
|
||||||
PoWConfig: powConfig,
|
PoWConfig: powConfig,
|
||||||
|
BasicAuthEnabled: route.BasicAuthEnabled,
|
||||||
|
BasicAuthUsername: route.BasicAuthUsername,
|
||||||
|
BasicAuthPassword: route.BasicAuthPassword,
|
||||||
Remark: route.Remark,
|
Remark: route.Remark,
|
||||||
CreatedAt: route.CreatedAt,
|
CreatedAt: route.CreatedAt,
|
||||||
UpdatedAt: route.UpdatedAt,
|
UpdatedAt: route.UpdatedAt,
|
||||||
|
|||||||
@@ -1020,6 +1020,118 @@ function PowSection({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const basicAuthSchema = z
|
||||||
|
.object({
|
||||||
|
basic_auth_enabled: z.boolean(),
|
||||||
|
basic_auth_username: z.string(),
|
||||||
|
basic_auth_password: z.string(),
|
||||||
|
})
|
||||||
|
.superRefine((value, context) => {
|
||||||
|
if (value.basic_auth_enabled) {
|
||||||
|
if (!value.basic_auth_username.trim()) {
|
||||||
|
context.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
path: ['basic_auth_username'],
|
||||||
|
message: '请输入账号',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!value.basic_auth_password.trim()) {
|
||||||
|
context.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
path: ['basic_auth_password'],
|
||||||
|
message: '请输入密码',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
type BasicAuthValues = z.infer<typeof basicAuthSchema>;
|
||||||
|
|
||||||
|
function BasicAuthSection({
|
||||||
|
route,
|
||||||
|
saving,
|
||||||
|
onSave,
|
||||||
|
}: {
|
||||||
|
route: ProxyRouteItem;
|
||||||
|
saving: boolean;
|
||||||
|
onSave: SaveHandler;
|
||||||
|
}) {
|
||||||
|
const form = useForm<BasicAuthValues>({
|
||||||
|
resolver: zodResolver(basicAuthSchema),
|
||||||
|
defaultValues: {
|
||||||
|
basic_auth_enabled: route.basic_auth_enabled,
|
||||||
|
basic_auth_username: route.basic_auth_username || '',
|
||||||
|
basic_auth_password: route.basic_auth_password || '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
form.reset({
|
||||||
|
basic_auth_enabled: route.basic_auth_enabled,
|
||||||
|
basic_auth_username: route.basic_auth_username || '',
|
||||||
|
basic_auth_password: route.basic_auth_password || '',
|
||||||
|
});
|
||||||
|
}, [form, route]);
|
||||||
|
|
||||||
|
const watchedEnabled = form.watch('basic_auth_enabled');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfigSectionShell
|
||||||
|
title="认证配置"
|
||||||
|
description="配置基础鉴权访问,需要输入账号密码才能访问网站。"
|
||||||
|
formId="proxy-route-auth-form"
|
||||||
|
saving={saving}
|
||||||
|
>
|
||||||
|
<form
|
||||||
|
id="proxy-route-auth-form"
|
||||||
|
className="space-y-5"
|
||||||
|
onSubmit={form.handleSubmit((values) => {
|
||||||
|
onSave(
|
||||||
|
buildPayloadFromRoute(route, {
|
||||||
|
basic_auth_enabled: values.basic_auth_enabled,
|
||||||
|
basic_auth_username: values.basic_auth_username.trim(),
|
||||||
|
basic_auth_password: values.basic_auth_password.trim(),
|
||||||
|
}),
|
||||||
|
{ message: '认证配置已保存。' },
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<ToggleField
|
||||||
|
label="启用 Basic Auth 鉴权"
|
||||||
|
description="拦截所有请求,需要输入正确的账号和密码才能访问。"
|
||||||
|
checked={watchedEnabled}
|
||||||
|
onChange={(checked) =>
|
||||||
|
form.setValue('basic_auth_enabled', checked, { shouldDirty: true })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ResourceField
|
||||||
|
label="账号"
|
||||||
|
error={form.formState.errors.basic_auth_username?.message}
|
||||||
|
>
|
||||||
|
<ResourceInput
|
||||||
|
disabled={!watchedEnabled}
|
||||||
|
placeholder="admin"
|
||||||
|
{...form.register('basic_auth_username')}
|
||||||
|
/>
|
||||||
|
</ResourceField>
|
||||||
|
|
||||||
|
<ResourceField
|
||||||
|
label="密码"
|
||||||
|
error={form.formState.errors.basic_auth_password?.message}
|
||||||
|
>
|
||||||
|
<ResourceInput
|
||||||
|
disabled={!watchedEnabled}
|
||||||
|
type="text"
|
||||||
|
placeholder="secret123"
|
||||||
|
{...form.register('basic_auth_password')}
|
||||||
|
/>
|
||||||
|
</ResourceField>
|
||||||
|
</form>
|
||||||
|
</ConfigSectionShell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function ProxyRouteConfigPage({
|
export function ProxyRouteConfigPage({
|
||||||
routeId,
|
routeId,
|
||||||
initialSection,
|
initialSection,
|
||||||
@@ -1240,6 +1352,16 @@ export function ProxyRouteConfigPage({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
{currentSection === 'auth' ? (
|
||||||
|
<BasicAuthSection
|
||||||
|
route={route}
|
||||||
|
saving={saveMutation.isPending}
|
||||||
|
onSave={(payload, context) =>
|
||||||
|
saveMutation.mutate({ payload, context })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -192,6 +192,9 @@ export function ProxyRouteCreateDrawer({
|
|||||||
custom_headers: [],
|
custom_headers: [],
|
||||||
pow_enabled: false,
|
pow_enabled: false,
|
||||||
pow_config: '{}',
|
pow_config: '{}',
|
||||||
|
basic_auth_enabled: false,
|
||||||
|
basic_auth_username: '',
|
||||||
|
basic_auth_password: '',
|
||||||
remark: values.remark.trim(),
|
remark: values.remark.trim(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ export const websiteConfigSections = [
|
|||||||
label: 'PoW 防护',
|
label: 'PoW 防护',
|
||||||
description: '配置 Proof-of-Work 反爬虫策略。',
|
description: '配置 Proof-of-Work 反爬虫策略。',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'auth',
|
||||||
|
label: '认证配置',
|
||||||
|
description: '配置基础鉴权访问,需要输入账号密码才能访问网站。',
|
||||||
|
},
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export type WebsiteConfigSectionKey =
|
export type WebsiteConfigSectionKey =
|
||||||
@@ -292,6 +297,9 @@ export function buildPayloadFromRoute(
|
|||||||
remark: route.remark || '',
|
remark: route.remark || '',
|
||||||
pow_enabled: route.pow_enabled,
|
pow_enabled: route.pow_enabled,
|
||||||
pow_config: JSON.stringify(route.pow_config),
|
pow_config: JSON.stringify(route.pow_config),
|
||||||
|
basic_auth_enabled: route.basic_auth_enabled,
|
||||||
|
basic_auth_username: route.basic_auth_username,
|
||||||
|
basic_auth_password: route.basic_auth_password,
|
||||||
...overrides,
|
...overrides,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ export interface ProxyRouteItem {
|
|||||||
custom_header_list: ProxyRouteCustomHeader[];
|
custom_header_list: ProxyRouteCustomHeader[];
|
||||||
pow_enabled: boolean;
|
pow_enabled: boolean;
|
||||||
pow_config: ProxyRoutePoWConfig;
|
pow_config: ProxyRoutePoWConfig;
|
||||||
|
basic_auth_enabled: boolean;
|
||||||
|
basic_auth_username: string;
|
||||||
|
basic_auth_password: string;
|
||||||
remark: string;
|
remark: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
@@ -81,6 +84,9 @@ export interface ProxyRouteMutationPayload {
|
|||||||
custom_headers: ProxyRouteCustomHeader[];
|
custom_headers: ProxyRouteCustomHeader[];
|
||||||
pow_enabled: boolean;
|
pow_enabled: boolean;
|
||||||
pow_config: string;
|
pow_config: string;
|
||||||
|
basic_auth_enabled: boolean;
|
||||||
|
basic_auth_username?: string;
|
||||||
|
basic_auth_password?: string;
|
||||||
remark: string;
|
remark: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user