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
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
46 additions
and
9 deletions
+46
-9
.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
+5
-3
web/src/features/auth/api.ts
+17
-5
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 @@
# 会话密钥
# SESSION_SECRET=random_string
# 登录密码请求体 RSA-OAEP 加密;默认关闭,且不能替代 HTTPS
# PASSWORD_LOGIN_ENCRYPTION_ENABLED=true
# false/未配置:本地 HTTP 模式,关闭 refresh/logout OriginGuard,且不得设置 TRUSTED_URL;兼容本地开发代理。
# true:启用 Secure Refresh Cookie 和严格 OriginGuard,必须同时列出全部可信 HTTPS Origin。
# SESSION_COOKIE_TRUSTED_URL 多项用英文逗号分隔;不支持通配符、路径或域名后缀匹配。
...
...
common/constants.go
View file @
918427d8
...
...
@@ -60,6 +60,7 @@ var ItemsPerPage = 10
var
MaxRecentItems
=
1000
var
PasswordLoginEnabled
=
true
var
PasswordLoginEncryptionEnabled
=
false
var
PasswordRegisterEnabled
=
true
var
EmailVerificationEnabled
=
false
var
GitHubOAuthEnabled
=
false
...
...
common/init.go
View file @
918427d8
...
...
@@ -87,6 +87,7 @@ func InitEnv() {
DebugEnabled
=
os
.
Getenv
(
"DEBUG"
)
==
"true"
MemoryCacheEnabled
=
os
.
Getenv
(
"MEMORY_CACHE_ENABLED"
)
==
"true"
IsMasterNode
=
os
.
Getenv
(
"NODE_TYPE"
)
!=
"slave"
PasswordLoginEncryptionEnabled
=
GetEnvOrDefaultBool
(
"PASSWORD_LOGIN_ENCRYPTION_ENABLED"
,
false
)
initNodeNameIdentity
()
TLSInsecureSkipVerify
=
GetEnvOrDefaultBool
(
"TLS_INSECURE_SKIP_VERIFY"
,
false
)
if
TLSInsecureSkipVerify
{
...
...
controller/misc.go
View file @
918427d8
...
...
@@ -94,6 +94,8 @@ func GetStatus(c *gin.Context) {
"password_register_enabled"
:
common
.
PasswordRegisterEnabled
,
"default_use_auto_group"
:
setting
.
DefaultUseAutoGroup
,
"password_login_encryption_enabled"
:
common
.
PasswordLoginEncryptionEnabled
,
"usd_exchange_rate"
:
operation_setting
.
USDExchangeRate
,
"price"
:
operation_setting
.
Price
,
"stripe_unit_price"
:
setting
.
StripeUnitPrice
,
...
...
controller/user.go
View file @
918427d8
...
...
@@ -40,12 +40,17 @@ var (
)
func
GetPasswordEncryptionKey
(
c
*
gin
.
Context
)
{
if
!
common
.
PasswordLoginEncryptionEnabled
{
common
.
ApiSuccess
(
c
,
gin
.
H
{
"enabled"
:
false
})
return
}
keyID
,
publicKey
:=
common
.
PasswordEncryptionPublicKey
()
if
keyID
==
""
||
publicKey
==
""
{
common
.
ApiErrorI18n
(
c
,
i18n
.
MsgDatabaseError
)
return
}
common
.
ApiSuccess
(
c
,
gin
.
H
{
"enabled"
:
true
,
"kid"
:
keyID
,
"public_key"
:
publicKey
,
})
...
...
@@ -64,7 +69,11 @@ func Login(c *gin.Context) {
}
username
:=
loginRequest
.
Username
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
)
if
err
!=
nil
{
common
.
ApiErrorI18n
(
c
,
i18n
.
MsgUserUsernameOrPasswordError
)
...
...
main.go
View file @
918427d8
...
...
@@ -318,9 +318,11 @@ func InitResources() error {
common
.
FatalLog
(
"failed to initialize authorization: "
+
err
.
Error
())
return
err
}
if
err
=
model
.
InitPasswordEncryption
();
err
!=
nil
{
common
.
FatalLog
(
"failed to initialize password encryption: "
+
err
.
Error
())
return
err
if
common
.
PasswordLoginEncryptionEnabled
{
if
err
=
model
.
InitPasswordEncryption
();
err
!=
nil
{
common
.
FatalLog
(
"failed to initialize password encryption: "
+
err
.
Error
())
return
err
}
}
model
.
CheckSetup
()
...
...
web/src/features/auth/api.ts
View file @
918427d8
...
...
@@ -48,22 +48,34 @@ import type {
export
async
function
login
(
payload
:
LoginPayload
):
Promise
<
LoginResponse
>
{
const
turnstile
=
payload
.
turnstile
??
''
try
{
const
encryptedPassword
=
await
encryptPassword
(
payload
.
password
)
let
passwordFields
:
|
{
password
:
string
}
|
{
password_encrypted
:
string
;
encryption_key_id
:
string
}
if
(
payload
.
passwordEncryptionEnabled
)
{
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
>
(
`/api/user/login?turnstile=
${
turnstile
}
`
,
{
username
:
payload
.
username
,
password_encrypted
:
encryptedPassword
.
password_encrypted
,
encryption_key_id
:
encryptedPassword
.
encryption_key_id
,
...
passwordFields
,
},
{
skipAuthRefresh
:
true
}
)
if
(
!
res
.
data
?.
success
)
{
if
(
payload
.
passwordEncryptionEnabled
&&
!
res
.
data
?.
success
)
{
clearPasswordEncryptionCache
()
}
return
res
.
data
}
catch
(
error
:
unknown
)
{
clearPasswordEncryptionCache
()
if
(
payload
.
passwordEncryptionEnabled
)
{
clearPasswordEncryptionCache
()
}
throw
error
}
}
...
...
web/src/features/auth/sign-in/components/user-auth-form.tsx
View file @
918427d8
...
...
@@ -84,6 +84,10 @@ export function UserAuthForm({
(
status
?.
password_login_enabled
??
status
?.
data
?.
password_login_enabled
??
true
)
!==
false
const
passwordLoginEncryptionEnabled
=
(
status
?.
password_login_encryption_enabled
??
status
?.
data
?.
password_login_encryption_enabled
??
false
)
===
true
const
{
isTurnstileEnabled
,
turnstileSiteKey
,
...
...
@@ -171,6 +175,7 @@ export function UserAuthForm({
username
:
data
.
username
,
password
:
data
.
password
,
turnstile
:
submittedTurnstileToken
,
passwordEncryptionEnabled
:
passwordLoginEncryptionEnabled
,
})
if
(
res
.
success
)
{
...
...
web/src/features/auth/types.ts
View file @
918427d8
...
...
@@ -26,6 +26,7 @@ export interface LoginPayload {
username
:
string
password
:
string
turnstile
?:
string
passwordEncryptionEnabled
?:
boolean
}
export
interface
TwoFAPayload
{
...
...
@@ -133,6 +134,7 @@ export interface SystemStatus {
oauth_register_enabled
?:
boolean
register_enabled
?:
boolean
password_login_enabled
?:
boolean
password_login_encryption_enabled
?:
boolean
password_register_enabled
?:
boolean
custom_oauth_providers
?:
CustomOAuthProviderInfo
[]
[
key
:
string
]:
unknown
...
...
@@ -178,6 +180,7 @@ export interface SystemStatus {
oauth_register_enabled
?:
boolean
register_enabled
?:
boolean
password_login_enabled
?:
boolean
password_login_encryption_enabled
?:
boolean
password_register_enabled
?:
boolean
custom_oauth_providers
?:
CustomOAuthProviderInfo
[]
[
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