fix(钉钉): 兼容桌面端免登来源
This commit is contained in:
parent
f4812dc6a2
commit
0b83ef7f88
@ -79,3 +79,16 @@ test('通知中心来源只可进入一次性票据回调', () => {
|
||||
path: '/api/equipment/1'
|
||||
}).status, 403)
|
||||
})
|
||||
|
||||
test('钉钉 WebView 的 null Origin 只可进入一次性票据回调', () => {
|
||||
assert.equal(runGuard({
|
||||
method: 'POST',
|
||||
origin: 'null',
|
||||
path: '/api/dingtalk/broker-login'
|
||||
}).nextCalls, 1)
|
||||
assert.equal(runGuard({
|
||||
method: 'POST',
|
||||
origin: 'null',
|
||||
path: '/api/equipment'
|
||||
}).status, 403)
|
||||
})
|
||||
|
||||
@ -45,6 +45,24 @@ test('跨源写操作默认拒绝,只单独放行通知中心票据回调', ()
|
||||
requestOrigin: 'https://asset.example.com',
|
||||
path: '/api/dingtalk/broker-login'
|
||||
}, env), true)
|
||||
assert.equal(isUnsafeRequestOriginAllowed({
|
||||
method: 'POST',
|
||||
origin: 'null',
|
||||
requestOrigin: 'https://asset.example.com',
|
||||
path: '/api/dingtalk/broker-login'
|
||||
}, env), true)
|
||||
assert.equal(isUnsafeRequestOriginAllowed({
|
||||
method: 'POST',
|
||||
origin: 'null',
|
||||
requestOrigin: 'https://asset.example.com',
|
||||
path: '/api/equipment'
|
||||
}, env), false)
|
||||
assert.equal(isUnsafeRequestOriginAllowed({
|
||||
method: 'POST',
|
||||
origin: 'https://evil.example.com',
|
||||
requestOrigin: 'https://asset.example.com',
|
||||
path: '/api/dingtalk/broker-login'
|
||||
}, env), false)
|
||||
assert.equal(isUnsafeRequestOriginAllowed({
|
||||
method: 'DELETE',
|
||||
origin: 'https://evil.example.com',
|
||||
|
||||
@ -39,11 +39,16 @@ export const isUnsafeRequestOriginAllowed = (input: {
|
||||
if (safeMethods.has(String(input.method || '').toUpperCase())) return true
|
||||
if (!input.origin) return true
|
||||
|
||||
const isBrokerCallback = input.path === '/api/dingtalk/broker-login'
|
||||
// 钉钉桌面 WebView 的跨域 form POST 会把 Origin 固定为 null。
|
||||
// 仅一次性票据回调接受该值;票据仍需通过项目签名兑换、受众校验、60秒过期和原子单次消费。
|
||||
if (isBrokerCallback && input.origin.trim().toLowerCase() === 'null') return true
|
||||
|
||||
const origin = parseOrigin(input.origin)
|
||||
const requestOrigin = parseOrigin(input.requestOrigin)
|
||||
if (!origin || !requestOrigin) return false
|
||||
if (origin === requestOrigin || getAllowedCorsOrigins(env).has(origin)) return true
|
||||
|
||||
const notificationCenterOrigin = parseOrigin(String(env.YYD_NOTIFICATION_CENTER_URL || '').trim())
|
||||
return input.path === '/api/dingtalk/broker-login' && origin === notificationCenterOrigin
|
||||
return isBrokerCallback && origin === notificationCenterOrigin
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user