78 lines
2.2 KiB
JavaScript
78 lines
2.2 KiB
JavaScript
|
|
const AUTO_START_KEY = 'oidc_auto_start_attempted'
|
|||
|
|
|
|||
|
|
// 对 redirect 参数进行安全校验,防止开放重定向漏洞
|
|||
|
|
// - 必须是字符串类型
|
|||
|
|
// - 必须以 / 开头(本地相对路径)
|
|||
|
|
// - 不能以 // 或 \ 开头(协议相对 URL / 非标准路径)
|
|||
|
|
// 不合法或缺失时返回 "/"
|
|||
|
|
export function sanitizeRedirect(value) {
|
|||
|
|
if (typeof value === 'string' && value.length > 0 && value[0] === '/' && value[1] !== '/' && value[1] !== '\\') {
|
|||
|
|
return value
|
|||
|
|
}
|
|||
|
|
return '/'
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查是否已经尝试过自动触发 OIDC(同一会话内,避免无限循环)
|
|||
|
|
export function hasAutoStartAttempted() {
|
|||
|
|
return sessionStorage.getItem(AUTO_START_KEY) === '1'
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 标记已尝试自动触发
|
|||
|
|
export function markAutoStartAttempted() {
|
|||
|
|
sessionStorage.setItem(AUTO_START_KEY, '1')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 清除自动触发尝试标记(OIDC 登录成功后调用)
|
|||
|
|
export function clearAutoStartAttempt() {
|
|||
|
|
sessionStorage.removeItem(AUTO_START_KEY)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 尝试自动触发 OIDC 登录
|
|||
|
|
// config: OIDC 配置对象(由调用方在外部获取)
|
|||
|
|
// getOIDCLoginUrl: 获取登录 URL 的异步函数
|
|||
|
|
// 返回 true 表示已发起跳转,caller 不应继续执行后续流程
|
|||
|
|
export async function tryAutoStartOIDC(getOIDCLoginUrl, config) {
|
|||
|
|
// 1. OIDC 配置未就绪或未启用
|
|||
|
|
if (!config || !config.enabled) {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 有 oidc_error 时不再自动触发,避免循环
|
|||
|
|
const params = new URLSearchParams(window.location.search)
|
|||
|
|
if (params.has('oidc_error')) {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. 必须有 autostartOidc 参数
|
|||
|
|
if (!params.has('autostartOidc')) {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. 同一会话内已尝试过,不再重复
|
|||
|
|
if (hasAutoStartAttempted()) {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 5. 获取 OIDC 登录 URL 并跳转
|
|||
|
|
let loginUrlResp
|
|||
|
|
try {
|
|||
|
|
loginUrlResp = await getOIDCLoginUrl()
|
|||
|
|
} catch {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!loginUrlResp || !loginUrlResp.login_url) {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 保存当前路径,登录后返回(安全校验)
|
|||
|
|
const redirectPath = sanitizeRedirect(params.get('redirect'))
|
|||
|
|
sessionStorage.setItem('oidc_redirect', redirectPath)
|
|||
|
|
|
|||
|
|
// 标记已尝试,防止下次再自动触发
|
|||
|
|
markAutoStartAttempted()
|
|||
|
|
|
|||
|
|
window.location.href = loginUrlResp.login_url
|
|||
|
|
return true
|
|||
|
|
}
|