@@ -587,7 +587,7 @@ const _initBase = _initProv === 'custom'
: (PROVS[_initProv]?.base||'https://api.yunwu.ai/v1');
const A = {
- key: ls('zy_key')||'',
+ key: sessionStorage.getItem('zy_key')||'',
base: _initBase,
mdl: ls('zy_mdl')||'gpt-4o',
prov: _initProv,
@@ -619,19 +619,16 @@ async function boot(){
// This is a reliable escape hatch when the UI cannot be navigated.
if(new URLSearchParams(location.search).get('reset')==='1'){
RESET_KEYS.forEach(k => localStorage.removeItem(k));
+ sessionStorage.removeItem('zy_key');
A.key=''; A.base=PROVS['yunwu'].base; A.mdl='gpt-4o'; A.prov='yunwu'; A.demo=false;
A.userName=''; A.ghUser=''; A.role='guest';
// Remove ?reset=1 from the URL so a subsequent refresh does not trigger another reset.
history.replaceState(null,'',location.pathname);
}
- // Sanitize: clear any stored key that contains the old KEY_MASK placeholder string.
- // Valid API keys are always alphanumeric (no Chinese characters), so this check
- // cannot produce false positives on a legitimate key.
- const storedKey = ls('zy_key');
- if(storedKey && storedKey.includes(KEY_MASK)){
- localStorage.removeItem('zy_key');
- A.key = '';
- }
+ // One-time migration: keys stored by old versions of this app in localStorage are
+ // no longer used (keys now live only in sessionStorage). Clear any stale value
+ // so it can never be accidentally picked up again.
+ localStorage.removeItem('zy_key');
initSetupUI();
// Restore identity from localStorage
if(A.userName) A.userMeta = ROLE_MAP[A.userName]||null;
@@ -699,7 +696,9 @@ function doSetup(){
let base = PROVS[pv]?.base||'';
if(pv==='custom') base=(document.getElementById('sep')?.value||'').trim()||base;
A.key=k; A.base=base; A.mdl=md; A.prov=pv; A.demo=false;
- lss('zy_key',k); lss('zy_base',base); lss('zy_mdl',md); lss('zy_prov',pv);
+ // Key is stored in sessionStorage only — it disappears when the tab/browser is closed.
+ // This prevents stale keys from persisting across sessions.
+ sessionStorage.setItem('zy_key', k); lss('zy_base',base); lss('zy_mdl',md); lss('zy_prov',pv);
// Save identity
const un = document.getElementById('suid').value;
const gh = (document.getElementById('sghuser')?.value||'').trim();
@@ -728,8 +727,8 @@ function initSettingsPanel(){
const hint = document.getElementById('ck-hint');
if(hint){
hint.textContent = A.key
- ? '🔒 当前已保存 Key 末4位:…'+(A.key.length>=4?A.key.slice(-4):A.key)+' · 留空保持不变,直接输入新 Key 即可替换'
- : '🔒 尚未设置 API 密钥,请输入后保存';
+ ? '🕐 密钥本次会话有效(末4位:…'+(A.key.length>=4?A.key.slice(-4):A.key)+')· 留空保持不变,输入新值即替换 · 关闭标签页自动清除'
+ : '🔒 密钥仅本次会话有效,关闭标签页自动清除,请输入后保存';
}
if(pv==='custom'){
document.getElementById('cep-g').style.display='block';
@@ -749,7 +748,9 @@ function saveSet(){
let base = PROVS[pv]?.base||'';
if(pv==='custom') base=(document.getElementById('cep').value.trim())||base;
A.key=k; A.base=base; A.mdl=md; A.prov=pv; A.demo=!k;
- lss('zy_key',k); lss('zy_base',base); lss('zy_mdl',md); lss('zy_prov',pv);
+ // Key lives in sessionStorage only — cleared when tab/browser closes.
+ if(k){ sessionStorage.setItem('zy_key', k); } else { sessionStorage.removeItem('zy_key'); }
+ lss('zy_base',base); lss('zy_mdl',md); lss('zy_prov',pv);
// Save identity
const un = document.getElementById('cuid')?.value||A.userName;
const gh = document.getElementById('cghuser')?.value?.trim()||A.ghUser;
@@ -768,6 +769,7 @@ function saveSet(){
function resetAllSettings(){
if(!confirm('确定要清除所有本地设置吗?\n\n· API 密钥会被删除\n· 身份设置会被删除\n· 将返回初始设置界面\n\n这不会影响任何聊天记录或云端数据。')) return;
RESET_KEYS.forEach(k => localStorage.removeItem(k));
+ sessionStorage.removeItem('zy_key');
window.location.reload();
}