Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
918427d8
authored
Aug 29, 2026
by
CaIon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(auth): make password encryption opt-in #6743
parent
8454082f
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
41 additions
and
4 deletions
+41
-4
.env.example
+2
-0
common/constants.go
+1
-0
common/init.go
+1
-0
controller/misc.go
+2
-0
controller/user.go
+10
-1
main.go
+2
-0
web/src/features/auth/api.ts
+15
-3
web/src/features/auth/sign-in/components/user-auth-form.tsx
+5
-0
web/src/features/auth/types.ts
+3
-0
No files found.
.env.example
View file @
918427d8
...
@@ -79,6 +79,8 @@
...
@@ -79,6 +79,8 @@
# 会话密钥
# 会话密钥
# SESSION_SECRET=random_string
# SESSION_SECRET=random_string
# 登录密码请求体 RSA-OAEP 加密;默认关闭,且不能替代 HTTPS
# PASSWORD_LOGIN_ENCRYPTION_ENABLED=true
# false/未配置:本地 HTTP 模式,关闭 refresh/logout OriginGuard,且不得设置 TRUSTED_URL;兼容本地开发代理。
# false/未配置:本地 HTTP 模式,关闭 refresh/logout OriginGuard,且不得设置 TRUSTED_URL;兼容本地开发代理。
# true:启用 Secure Refresh Cookie 和严格 OriginGuard,必须同时列出全部可信 HTTPS Origin。
# true:启用 Secure Refresh Cookie 和严格 OriginGuard,必须同时列出全部可信 HTTPS Origin。
# SESSION_COOKIE_TRUSTED_URL 多项用英文逗号分隔;不支持通配符、路径或域名后缀匹配。
# SESSION_COOKIE_TRUSTED_URL 多项用英文逗号分隔;不支持通配符、路径或域名后缀匹配。
...
...
common/constants.go
View file @
918427d8
...
@@ -60,6 +60,7 @@ var ItemsPerPage = 10
...
@@ -60,6 +60,7 @@ var ItemsPerPage = 10
var
MaxRecentItems
=
1000
var
MaxRecentItems
=
1000
var
PasswordLoginEnabled
=
true
var
PasswordLoginEnabled
=
true
var
PasswordLoginEncryptionEnabled
=
false
var
PasswordRegisterEnabled
=
true
var
PasswordRegisterEnabled
=
true
var
EmailVerificationEnabled
=
false
var
EmailVerificationEnabled
=
false
var
GitHubOAuthEnabled
=
false
var
GitHubOAuthEnabled
=
false
...
...
common/init.go
View file @
918427d8
...
@@ -87,6 +87,7 @@ func InitEnv() {
...
@@ -87,6 +87,7 @@ func InitEnv() {
DebugEnabled
=
os
.
Getenv
(
"DEBUG"
)
==
"true"
DebugEnabled
=
os
.
Getenv
(
"DEBUG"
)
==
"true"
MemoryCacheEnabled
=
os
.
Getenv
(
"MEMORY_CACHE_ENABLED"
)
==
"true"
MemoryCacheEnabled
=
os
.
Getenv
(
"MEMORY_CACHE_ENABLED"
)
==
"true"
IsMasterNode
=
os
.
Getenv
(
"NODE_TYPE"
)
!=
"slave"
IsMasterNode
=
os
.
Getenv
(
"NODE_TYPE"
)
!=
"slave"
PasswordLoginEncryptionEnabled
=
GetEnvOrDefaultBool
(
"PASSWORD_LOGIN_ENCRYPTION_ENABLED"
,
false
)
initNodeNameIdentity
()
initNodeNameIdentity
()
TLSInsecureSkipVerify
=
GetEnvOrDefaultBool
(
"TLS_INSECURE_SKIP_VERIFY"
,
false
)
TLSInsecureSkipVerify
=
GetEnvOrDefaultBool
(
"TLS_INSECURE_SKIP_VERIFY"
,
false
)
if
TLSInsecureSkipVerify
{
if
TLSInsecureSkipVerify
{
...
...
controller/misc.go
View file @
918427d8
...
@@ -94,6 +94,8 @@ func GetStatus(c *gin.Context) {
...
@@ -94,6 +94,8 @@ func GetStatus(c *gin.Context) {
"password_register_enabled"
:
common
.
PasswordRegisterEnabled
,
"password_register_enabled"
:
common
.
PasswordRegisterEnabled
,
"default_use_auto_group"
:
setting
.
DefaultUseAutoGroup
,
"default_use_auto_group"
:
setting
.
DefaultUseAutoGroup
,
"password_login_encryption_enabled"
:
common
.
PasswordLoginEncryptionEnabled
,
"usd_exchange_rate"
:
operation_setting
.
USDExchangeRate
,
"usd_exchange_rate"
:
operation_setting
.
USDExchangeRate
,
"price"
:
operation_setting
.
Price
,
"price"
:
operation_setting
.
Price
,
"stripe_unit_price"
:
setting
.
StripeUnitPrice
,
"stripe_unit_price"
:
setting
.
StripeUnitPrice
,
...
...
controller/user.go
View file @
918427d8
...
@@ -40,12 +40,17 @@ var (
...
@@ -40,12 +40,17 @@ var (
)
)
func
GetPasswordEncryptionKey
(
c
*
gin
.
Context
)
{
func
GetPasswordEncryptionKey
(
c
*
gin
.
Context
)
{
if
!
common
.
PasswordLoginEncryptionEnabled
{
common
.
ApiSuccess
(
c
,
gin
.
H
{
"enabled"
:
false
})
return
}
keyID
,
publicKey
:=
common
.
PasswordEncryptionPublicKey
()
keyID
,
publicKey
:=
common
.
PasswordEncryptionPublicKey
()
if
keyID
==
""
||
publicKey
==
""
{
if
keyID
==
""
||
publicKey
==
""
{
common
.
ApiErrorI18n
(
c
,
i18n
.
MsgDatabaseError
)
common
.
ApiErrorI18n
(
c
,
i18n
.
MsgDatabaseError
)
return
return
}
}
common
.
ApiSuccess
(
c
,
gin
.
H
{
common
.
ApiSuccess
(
c
,
gin
.
H
{
"enabled"
:
true
,
"kid"
:
keyID
,
"kid"
:
keyID
,
"public_key"
:
publicKey
,
"public_key"
:
publicKey
,
})
})
...
@@ -64,7 +69,11 @@ func Login(c *gin.Context) {
...
@@ -64,7 +69,11 @@ func Login(c *gin.Context) {
}
}
username
:=
loginRequest
.
Username
username
:=
loginRequest
.
Username
password
:=
loginRequest
.
Password
password
:=
loginRequest
.
Password
if
loginRequest
.
PasswordEncrypted
!=
""
{
if
common
.
PasswordLoginEncryptionEnabled
{
if
loginRequest
.
PasswordEncrypted
==
""
||
loginRequest
.
EncryptionKeyID
==
""
{
common
.
ApiErrorI18n
(
c
,
i18n
.
MsgInvalidParams
)
return
}
password
,
err
=
common
.
DecryptPassword
(
loginRequest
.
PasswordEncrypted
,
loginRequest
.
EncryptionKeyID
)
password
,
err
=
common
.
DecryptPassword
(
loginRequest
.
PasswordEncrypted
,
loginRequest
.
EncryptionKeyID
)
if
err
!=
nil
{
if
err
!=
nil
{
common
.
ApiErrorI18n
(
c
,
i18n
.
MsgUserUsernameOrPasswordError
)
common
.
ApiErrorI18n
(
c
,
i18n
.
MsgUserUsernameOrPasswordError
)
...
...
main.go
View file @
918427d8
...
@@ -318,10 +318,12 @@ func InitResources() error {
...
@@ -318,10 +318,12 @@ func InitResources() error {
common
.
FatalLog
(
"failed to initialize authorization: "
+
err
.
Error
())
common
.
FatalLog
(
"failed to initialize authorization: "
+
err
.
Error
())
return
err
return
err
}
}
if
common
.
PasswordLoginEncryptionEnabled
{
if
err
=
model
.
InitPasswordEncryption
();
err
!=
nil
{
if
err
=
model
.
InitPasswordEncryption
();
err
!=
nil
{
common
.
FatalLog
(
"failed to initialize password encryption: "
+
err
.
Error
())
common
.
FatalLog
(
"failed to initialize password encryption: "
+
err
.
Error
())
return
err
return
err
}
}
}
model
.
CheckSetup
()
model
.
CheckSetup
()
...
...
web/src/features/auth/api.ts
View file @
918427d8
...
@@ -48,22 +48,34 @@ import type {
...
@@ -48,22 +48,34 @@ import type {
export
async
function
login
(
payload
:
LoginPayload
):
Promise
<
LoginResponse
>
{
export
async
function
login
(
payload
:
LoginPayload
):
Promise
<
LoginResponse
>
{
const
turnstile
=
payload
.
turnstile
??
''
const
turnstile
=
payload
.
turnstile
??
''
try
{
try
{
let
passwordFields
:
|
{
password
:
string
}
|
{
password_encrypted
:
string
;
encryption_key_id
:
string
}
if
(
payload
.
passwordEncryptionEnabled
)
{
const
encryptedPassword
=
await
encryptPassword
(
payload
.
password
)
const
encryptedPassword
=
await
encryptPassword
(
payload
.
password
)
passwordFields
=
{
password_encrypted
:
encryptedPassword
.
password_encrypted
,
encryption_key_id
:
encryptedPassword
.
encryption_key_id
,
}
}
else
{
passwordFields
=
{
password
:
payload
.
password
}
}
const
res
=
await
api
.
post
<
LoginResponse
>
(
const
res
=
await
api
.
post
<
LoginResponse
>
(
`/api/user/login?turnstile=
${
turnstile
}
`
,
`/api/user/login?turnstile=
${
turnstile
}
`
,
{
{
username
:
payload
.
username
,
username
:
payload
.
username
,
password_encrypted
:
encryptedPassword
.
password_encrypted
,
...
passwordFields
,
encryption_key_id
:
encryptedPassword
.
encryption_key_id
,
},
},
{
skipAuthRefresh
:
true
}
{
skipAuthRefresh
:
true
}
)
)
if
(
!
res
.
data
?.
success
)
{
if
(
payload
.
passwordEncryptionEnabled
&&
!
res
.
data
?.
success
)
{
clearPasswordEncryptionCache
()
clearPasswordEncryptionCache
()
}
}
return
res
.
data
return
res
.
data
}
catch
(
error
:
unknown
)
{
}
catch
(
error
:
unknown
)
{
if
(
payload
.
passwordEncryptionEnabled
)
{
clearPasswordEncryptionCache
()
clearPasswordEncryptionCache
()
}
throw
error
throw
error
}
}
}
}
...
...
web/src/features/auth/sign-in/components/user-auth-form.tsx
View file @
918427d8
...
@@ -84,6 +84,10 @@ export function UserAuthForm({
...
@@ -84,6 +84,10 @@ export function UserAuthForm({
(
status
?.
password_login_enabled
??
(
status
?.
password_login_enabled
??
status
?.
data
?.
password_login_enabled
??
status
?.
data
?.
password_login_enabled
??
true
)
!==
false
true
)
!==
false
const
passwordLoginEncryptionEnabled
=
(
status
?.
password_login_encryption_enabled
??
status
?.
data
?.
password_login_encryption_enabled
??
false
)
===
true
const
{
const
{
isTurnstileEnabled
,
isTurnstileEnabled
,
turnstileSiteKey
,
turnstileSiteKey
,
...
@@ -171,6 +175,7 @@ export function UserAuthForm({
...
@@ -171,6 +175,7 @@ export function UserAuthForm({
username
:
data
.
username
,
username
:
data
.
username
,
password
:
data
.
password
,
password
:
data
.
password
,
turnstile
:
submittedTurnstileToken
,
turnstile
:
submittedTurnstileToken
,
passwordEncryptionEnabled
:
passwordLoginEncryptionEnabled
,
})
})
if
(
res
.
success
)
{
if
(
res
.
success
)
{
...
...
web/src/features/auth/types.ts
View file @
918427d8
...
@@ -26,6 +26,7 @@ export interface LoginPayload {
...
@@ -26,6 +26,7 @@ export interface LoginPayload {
username
:
string
username
:
string
password
:
string
password
:
string
turnstile
?:
string
turnstile
?:
string
passwordEncryptionEnabled
?:
boolean
}
}
export
interface
TwoFAPayload
{
export
interface
TwoFAPayload
{
...
@@ -133,6 +134,7 @@ export interface SystemStatus {
...
@@ -133,6 +134,7 @@ export interface SystemStatus {
oauth_register_enabled
?:
boolean
oauth_register_enabled
?:
boolean
register_enabled
?:
boolean
register_enabled
?:
boolean
password_login_enabled
?:
boolean
password_login_enabled
?:
boolean
password_login_encryption_enabled
?:
boolean
password_register_enabled
?:
boolean
password_register_enabled
?:
boolean
custom_oauth_providers
?:
CustomOAuthProviderInfo
[]
custom_oauth_providers
?:
CustomOAuthProviderInfo
[]
[
key
:
string
]:
unknown
[
key
:
string
]:
unknown
...
@@ -178,6 +180,7 @@ export interface SystemStatus {
...
@@ -178,6 +180,7 @@ export interface SystemStatus {
oauth_register_enabled
?:
boolean
oauth_register_enabled
?:
boolean
register_enabled
?:
boolean
register_enabled
?:
boolean
password_login_enabled
?:
boolean
password_login_enabled
?:
boolean
password_login_encryption_enabled
?:
boolean
password_register_enabled
?:
boolean
password_register_enabled
?:
boolean
custom_oauth_providers
?:
CustomOAuthProviderInfo
[]
custom_oauth_providers
?:
CustomOAuthProviderInfo
[]
[
key
:
string
]:
unknown
[
key
:
string
]:
unknown
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment