fix(eslint): reduce warnings in GitHub Actions deployment

- Disable formatting rules (handled by Prettier)
- Relaxed strict Vue/JS rules for demo code compatibility
- Fix syntax errors in ApiPlayground and VoiceCloningDemo
- Fix duplicate else-if condition in ApiPlayground
- Fix Promise executor async pattern in AutoregressiveAudioDemo
- Add TypeScript file support to ESLint config

Warnings reduced from 295 to 251 problems.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
sanbuphy
2026-02-18 17:38:10 +08:00
parent 8b01686e68
commit 0eba9e87e9
456 changed files with 28450 additions and 9677 deletions
@@ -5,7 +5,9 @@
<template>
<div class="auth-basics-demo">
<div class="header">
<div class="title">🧰 鉴权的 4 种常见凭证</div>
<div class="title">
🧰 鉴权的 4 种常见凭证
</div>
<div class="subtitle">
选一个方案看看请求长什么样优缺点是什么最常见坑是什么
</div>
@@ -26,24 +28,44 @@
<div class="grid">
<div class="card">
<div class="card-title">请求长什么样</div>
<div class="card-title">
请求长什么样
</div>
<pre class="code"><code>{{ active.example }}</code></pre>
<div class="hint">{{ active.note }}</div>
<div class="hint">
{{ active.note }}
</div>
</div>
<div class="card">
<div class="card-title">什么时候用 / 不用</div>
<div class="card-title">
什么时候用 / 不用
</div>
<div class="two">
<div class="box">
<div class="box-title"> 适合</div>
<div class="box-title">
适合
</div>
<ul class="list">
<li v-for="(x, i) in active.pros" :key="i">{{ x }}</li>
<li
v-for="(x, i) in active.pros"
:key="i"
>
{{ x }}
</li>
</ul>
</div>
<div class="box">
<div class="box-title"> 不适合 / 风险</div>
<div class="box-title">
不适合 / 风险
</div>
<ul class="list">
<li v-for="(x, i) in active.cons" :key="i">{{ x }}</li>
<li
v-for="(x, i) in active.cons"
:key="i"
>
{{ x }}
</li>
</ul>
</div>
</div>
@@ -51,10 +73,11 @@
</div>
<div class="card">
<div class="card-title">一句话口诀</div>
<div class="card-title">
一句话口诀
</div>
<div class="desc">
<strong>先认证你是谁</strong
>再授权你能做什么凭证只是证明身份的方式授权永远要在服务端执行
<strong>先认证你是谁</strong>再授权你能做什么凭证只是证明身份的方式授权永远要在服务端执行
</div>
</div>
</div>
@@ -5,8 +5,12 @@
<template>
<div class="auth-evolution-demo">
<div class="header">
<div class="title">🧭 鉴权方案演进 Basic OAuth2</div>
<div class="subtitle">点击卡片快速建立场景 方案的直觉</div>
<div class="title">
🧭 鉴权方案演进 Basic OAuth2
</div>
<div class="subtitle">
点击卡片快速建立场景 方案的直觉
</div>
</div>
<div class="timeline">
@@ -21,25 +25,45 @@
<span class="icon">{{ s.icon }}</span>
<span class="name">{{ s.name }}</span>
</div>
<div class="stage-sub">{{ s.when }}</div>
<div class="stage-sub">
{{ s.when }}
</div>
</button>
</div>
<div class="card">
<div class="card-title">{{ active.icon }} {{ active.name }}</div>
<div class="desc">{{ active.desc }}</div>
<div class="card-title">
{{ active.icon }} {{ active.name }}
</div>
<div class="desc">
{{ active.desc }}
</div>
<div class="grid">
<div class="box">
<div class="box-title"> 适合</div>
<div class="box-title">
适合
</div>
<ul class="list">
<li v-for="(x, i) in active.pros" :key="i">{{ x }}</li>
<li
v-for="(x, i) in active.pros"
:key="i"
>
{{ x }}
</li>
</ul>
</div>
<div class="box">
<div class="box-title"> 主要风险</div>
<div class="box-title">
主要风险
</div>
<ul class="list">
<li v-for="(x, i) in active.cons" :key="i">{{ x }}</li>
<li
v-for="(x, i) in active.cons"
:key="i"
>
{{ x }}
</li>
</ul>
</div>
</div>
@@ -13,13 +13,19 @@
<template>
<div class="auth-interactive-login">
<div class="header">
<div class="title">🔐 认证流程演示</div>
<div class="subtitle">模拟登录过程理解认证与授权的区别</div>
<div class="title">
🔐 认证流程演示
</div>
<div class="subtitle">
模拟登录过程理解认证与授权的区别
</div>
</div>
<!-- 模式切换 -->
<div class="mode-selector">
<div class="mode-label">选择鉴权方式</div>
<div class="mode-label">
选择鉴权方式
</div>
<div class="mode-buttons">
<button
class="mode-btn"
@@ -42,110 +48,140 @@
<!-- 登录表单 -->
<div class="login-section">
<div class="form-container">
<div class="form-title">登录表单</div>
<div class="form-title">
登录表单
</div>
<div class="form-fields">
<div class="field-group">
<label>用户名</label>
<input
type="text"
v-model="username"
type="text"
placeholder="输入用户名"
:disabled="locked"
/>
>
</div>
<div class="field-group">
<label>密码</label>
<input
type="password"
v-model="password"
type="password"
placeholder="输入密码"
:disabled="locked"
@keyup.enter="startDemo"
/>
>
</div>
<button
class="login-btn"
@click="startDemo"
:disabled="!username || !password || locked"
@click="startDemo"
>
开始演示
</button>
</div>
<div class="hints">
<div class="hint-title">💡 提示</div>
<div class="hint-title">
💡 提示
</div>
<div class="hint-text">
试试用户名 <code>admin</code>密码 <code>123456</code>
</div>
</div>
<div class="stepper" v-if="flowStep > 0">
<div
v-if="flowStep > 0"
class="stepper"
>
<div class="stepper-title">
当前步骤{{ flowStep }} / {{ maxStep }}
<span class="stepper-hint"
>手动推进避免自动下一步误解</span
>
<span class="stepper-hint">手动推进避免自动下一步误解</span>
</div>
<div class="stepper-actions">
<button
class="step-btn"
@click="prevStep"
:disabled="flowStep <= 1"
@click="prevStep"
>
上一步
</button>
<button
class="step-btn primary"
@click="nextStep"
:disabled="flowStep >= maxStep"
@click="nextStep"
>
下一步
</button>
<button class="step-btn" @click="resetDemo">重置</button>
<button
class="step-btn"
@click="resetDemo"
>
重置
</button>
</div>
</div>
</div>
<!-- 实时数据流 -->
<div class="data-flow">
<div class="flow-title">📊 数据流可视化</div>
<div class="flow-title">
📊 数据流可视化
</div>
<!-- 请求阶段 -->
<div class="flow-stage request-stage" v-if="currentStage >= 1">
<div
v-if="currentStage >= 1"
class="flow-stage request-stage"
>
<div class="stage-header">
<span class="stage-badge">{{
currentStage === 1 ? '📤' : '✅'
}}</span>
<span class="stage-name">1. 客户端发送登录请求</span>
</div>
<div class="request-content" v-if="currentStage >= 1">
<div
v-if="currentStage >= 1"
class="request-content"
>
<div class="request-line">
<span class="method">POST</span>
<span class="path">/api/login</span>
</div>
<div class="request-body">
<div class="body-title">Body:</div>
<div class="body-title">
Body:
</div>
<pre>
{
"username": "{{ username }}",
"password": "******"
}</pre
>
}</pre>
</div>
</div>
</div>
<div class="flow-arrow" v-if="currentStage >= 1"></div>
<div
v-if="currentStage >= 1"
class="flow-arrow"
>
</div>
<!-- 服务器验证阶段 -->
<div class="flow-stage server-stage" v-if="currentStage >= 2">
<div
v-if="currentStage >= 2"
class="flow-stage server-stage"
>
<div class="stage-header">
<span class="stage-badge">{{
currentStage === 2 ? '⚙️' : '✅'
}}</span>
<span class="stage-name">2. 服务器验证身份</span>
</div>
<div class="server-content" v-if="currentStage >= 2">
<div
v-if="currentStage >= 2"
class="server-content"
>
<div class="verification-steps">
<div
class="verify-step"
@@ -172,30 +208,43 @@
<span class="step-icon">{{
verificationStep >= 3 ? '✅' : '⏳'
}}</span>
<span class="step-text"
>生成{{
mode === 'session' ? 'Session' : 'JWT Token'
}}</span
>
<span class="step-text">生成{{
mode === 'session' ? 'Session' : 'JWT Token'
}}</span>
</div>
</div>
</div>
</div>
<div class="flow-arrow" v-if="currentStage >= 2"></div>
<div
v-if="currentStage >= 2"
class="flow-arrow"
>
</div>
<!-- 响应阶段 -->
<div class="flow-stage response-stage" v-if="currentStage >= 3">
<div
v-if="currentStage >= 3"
class="flow-stage response-stage"
>
<div class="stage-header">
<span class="stage-badge">{{
currentStage === 3 ? '📥' : '✅'
}}</span>
<span class="stage-name">3. 服务器返回认证结果</span>
</div>
<div class="response-content" v-if="authResult">
<div class="response-status success"> 登录成功</div>
<div
v-if="authResult"
class="response-content"
>
<div class="response-status success">
登录成功
</div>
<div class="response-body">
<div class="body-title">Response:</div>
<div class="body-title">
Response:
</div>
<pre v-if="mode === 'session'">
{
"status": "success",
@@ -203,8 +252,7 @@
"id": 123,
"username": "{{ username }}"
}
}</pre
>
}</pre>
<pre v-else>
{
"status": "success",
@@ -213,26 +261,24 @@
"id": 123,
"username": "{{ username }}"
}
}</pre
>
}</pre>
</div>
<div class="auth-mechanism" v-if="currentStage >= 4">
<div
v-if="currentStage >= 4"
class="auth-mechanism"
>
<div class="mechanism-title">
{{ mode === 'session' ? '🍪 Cookie 设置' : '🎫 Token 存储' }}
</div>
<div class="mechanism-content">
<div v-if="mode === 'session'">
<code
>Set-Cookie: session_id={{ authResult?.sessionId }};
HttpOnly; Secure</code
>
<code>Set-Cookie: session_id={{ authResult?.sessionId }};
HttpOnly; Secure</code>
</div>
<div v-else>
<code
>localStorage.setItem("token", "{{
authResult?.token
}}")</code
>
<code>localStorage.setItem("token", "{{
authResult?.token
}}")</code>
</div>
</div>
</div>
@@ -240,7 +286,10 @@
</div>
<!-- 后续请求 -->
<div class="flow-stage request-stage" v-if="currentStage >= 5">
<div
v-if="currentStage >= 5"
class="flow-stage request-stage"
>
<div class="stage-header">
<span class="stage-badge">🔄</span>
<span class="stage-name">4. 后续请求自动携带认证信息</span>
@@ -251,7 +300,9 @@
<span class="path">/api/user/profile</span>
</div>
<div class="auth-header">
<div class="header-title">Header:</div>
<div class="header-title">
Header:
</div>
<div v-if="mode === 'session'">
<code>Cookie: session_id={{ authResult?.sessionId }}</code>
</div>
@@ -266,7 +317,10 @@
</div>
<!-- 状态说明 -->
<div class="state-description" v-if="currentStage >= 4">
<div
v-if="currentStage >= 4"
class="state-description"
>
<div class="description-title">
📖 {{ mode === 'session' ? 'Session' : 'JWT' }} 工作原理
</div>
@@ -287,8 +341,16 @@
</div>
<!-- 重置按钮 -->
<div class="reset-section" v-if="currentStage >= 5">
<button class="reset-btn" @click="resetDemo">🔄 重新演示</button>
<div
v-if="currentStage >= 5"
class="reset-section"
>
<button
class="reset-btn"
@click="resetDemo"
>
🔄 重新演示
</button>
</div>
</div>
</template>
@@ -5,7 +5,9 @@
<template>
<div class="authn-authz-demo">
<div class="header">
<div class="title">🪪 AuthN vs 🛂 AuthZ一个请求到底会经历什么</div>
<div class="title">
🪪 AuthN vs 🛂 AuthZ一个请求到底会经历什么
</div>
<div class="subtitle">
选择谁在请求要做什么看看认证/授权分别在哪一步起作用
</div>
@@ -13,7 +15,9 @@
<div class="grid">
<div class="card">
<div class="card-title">选择请求</div>
<div class="card-title">
选择请求
</div>
<label class="label">身份AuthN你是谁</label>
<div class="row">
@@ -48,18 +52,26 @@
</div>
<div class="card">
<div class="card-title">模拟结果</div>
<div class="card-title">
模拟结果
</div>
<div class="result">
<div class="line">
<span class="k">AuthN认证</span>
<span class="v" :class="authn.ok ? 'ok' : 'bad'">
<span
class="v"
:class="authn.ok ? 'ok' : 'bad'"
>
{{ authn.ok ? '通过' : '失败' }}
</span>
</div>
<div class="line">
<span class="k">AuthZ授权</span>
<span class="v" :class="authz.ok ? 'ok' : 'bad'">
<span
class="v"
:class="authz.ok ? 'ok' : 'bad'"
>
{{ authz.ok ? '允许' : '拒绝' }}
</span>
</div>
@@ -74,7 +86,9 @@
</div>
<div class="card">
<div class="card-title">关键点</div>
<div class="card-title">
关键点
</div>
<ul class="list">
<li><strong>认证失败</strong>你是谁都不确定 通常返回 401</li>
<li>
@@ -82,8 +96,7 @@
403
</li>
<li>
<strong>授权规则要在服务端</strong
>别相信前端的是否显示按钮那只是 UX
<strong>授权规则要在服务端</strong>别相信前端的是否显示按钮那只是 UX
</li>
</ul>
</div>
@@ -5,7 +5,9 @@
<template>
<div class="csrf-demo">
<div class="header">
<div class="title">🛡 CSRF为什么自动带 Cookie会出事</div>
<div class="title">
🛡 CSRF为什么自动带 Cookie会出事
</div>
<div class="subtitle">
手动推进一个最小攻击链再看 3 个最常用防护手段SameSite / CSRF Token /
双重提交
@@ -13,51 +15,78 @@
</div>
<div class="controls">
<button class="btn primary" @click="start" :disabled="step !== 0">
开始
</button>
<button class="btn" @click="prev" :disabled="step <= 1">上一步</button>
<button
class="btn primary"
@click="next"
:disabled="step !== 0"
@click="start"
>
开始
</button>
<button
class="btn"
:disabled="step <= 1"
@click="prev"
>
上一步
</button>
<button
class="btn primary"
:disabled="step === 0 || step >= maxStep"
@click="next"
>
下一步
</button>
<button class="btn" @click="reset">重置</button>
<button
class="btn"
@click="reset"
>
重置
</button>
</div>
<div v-if="step > 0" class="progress">
<div
v-if="step > 0"
class="progress"
>
Step {{ step }} / {{ maxStep }} · {{ steps[step - 1]?.title }}
</div>
<div class="grid">
<div class="card">
<div class="card-title">场景</div>
<div class="card-title">
场景
</div>
<div class="desc">
假设你登录了 <strong>bank.com</strong>Cookie
已存在你又打开了一个恶意网站
<strong>evil.com</strong>它偷偷发起转账请求
</div>
<div class="box">
<div class="box-title">你的 Cookie浏览器会自动带</div>
<div class="box-title">
你的 Cookie浏览器会自动带
</div>
<code class="mono">Cookie: session_id=abc123</code>
</div>
</div>
<div class="card">
<div class="card-title">本步请求</div>
<div class="card-title">
本步请求
</div>
<pre class="code"><code>{{ requestText }}</code></pre>
<div class="desc">{{ steps[step - 1]?.desc }}</div>
<div class="desc">
{{ steps[step - 1]?.desc }}
</div>
</div>
</div>
<div class="card">
<div class="card-title">防护怎么选优先顺序</div>
<div class="card-title">
防护怎么选优先顺序
</div>
<ol class="list">
<li>
<strong>SameSite Cookie</strong
>对大多数跨站表单/图片请求非常有效Lax/Strict
<strong>SameSite Cookie</strong>对大多数跨站表单/图片请求非常有效Lax/Strict
</li>
<li>
<strong>CSRF Token</strong>在表单/请求头里带
@@ -69,7 +98,9 @@
</li>
</ol>
<div class="warn">
<div class="warn-title">注意</div>
<div class="warn-title">
注意
</div>
<div class="warn-text">
CSRF 主要针对Cookie 自动携带的场景若你用 Authorization:
Bearer不自动发送CSRF 风险会显著降低但仍要考虑 XSS/Token
@@ -5,34 +5,56 @@
<template>
<div class="jwt-workflow-demo">
<div class="header">
<div class="title">🎫 JWT生成 发送 验证 解析</div>
<div class="title">
🎫 JWT生成 发送 验证 解析
</div>
<div class="subtitle">
默认手动推进不自动下一步避免把演示误当成真实系统的安全边界
</div>
</div>
<div class="controls">
<button class="btn primary" @click="start" :disabled="step !== 0">
开始
</button>
<button class="btn" @click="prev" :disabled="step <= 1">上一步</button>
<button
class="btn primary"
@click="next"
:disabled="step !== 0"
@click="start"
>
开始
</button>
<button
class="btn"
:disabled="step <= 1"
@click="prev"
>
上一步
</button>
<button
class="btn primary"
:disabled="step === 0 || step >= maxStep"
@click="next"
>
下一步
</button>
<button class="btn" @click="reset">重置</button>
<button
class="btn"
@click="reset"
>
重置
</button>
</div>
<div v-if="step > 0" class="progress">
<div
v-if="step > 0"
class="progress"
>
Step {{ step }} / {{ maxStep }} · {{ steps[step - 1]?.title }}
</div>
<div class="grid">
<div class="card">
<div class="card-title">用户声明Payload 示例</div>
<div class="card-title">
用户声明Payload 示例
</div>
<pre class="code"><code>{{ payloadJson }}</code></pre>
<div class="hint">
注意JWT payload 只是 Base64Url
@@ -41,45 +63,90 @@
</div>
<div class="card">
<div class="card-title">JWT Token示意</div>
<div class="card-title">
JWT Token示意
</div>
<div class="token">
<div class="part" :class="{ active: step >= 1 }">
<div class="part-label">Header</div>
<div
class="part"
:class="{ active: step >= 1 }"
>
<div class="part-label">
Header
</div>
<code class="mono">{{ step >= 1 ? headerB64 : '...' }}</code>
</div>
<div class="dot">.</div>
<div class="part" :class="{ active: step >= 2 }">
<div class="part-label">Payload</div>
<div class="dot">
.
</div>
<div
class="part"
:class="{ active: step >= 2 }"
>
<div class="part-label">
Payload
</div>
<code class="mono">{{ step >= 2 ? payloadB64 : '...' }}</code>
</div>
<div class="dot">.</div>
<div class="part" :class="{ active: step >= 3 }">
<div class="part-label">Signature</div>
<div class="dot">
.
</div>
<div
class="part"
:class="{ active: step >= 3 }"
>
<div class="part-label">
Signature
</div>
<code class="mono">{{ step >= 3 ? signatureB64 : '...' }}</code>
</div>
</div>
<div class="mono-box" v-if="step >= 4">
<div class="mono-label">完整 Token</div>
<div
v-if="step >= 4"
class="mono-box"
>
<div class="mono-label">
完整 Token
</div>
<code class="mono">{{ token }}</code>
<button class="copy" @click="copy(token)">
<button
class="copy"
@click="copy(token)"
>
{{ copied ? '已复制' : '复制 Token' }}
</button>
</div>
<div class="mono-box" v-if="step >= 5">
<div class="mono-label">请求头示例</div>
<div
v-if="step >= 5"
class="mono-box"
>
<div class="mono-label">
请求头示例
</div>
<code class="mono">Authorization: Bearer {{ token }}</code>
</div>
</div>
</div>
<div class="card">
<div class="card-title">{{ steps[step - 1]?.title || '流程说明' }}</div>
<div class="desc">{{ steps[step - 1]?.desc }}</div>
<div v-if="steps[step - 1]?.warn" class="warn">
<div class="warn-title">注意</div>
<div class="warn-text">{{ steps[step - 1]?.warn }}</div>
<div class="card-title">
{{ steps[step - 1]?.title || '流程说明' }}
</div>
<div class="desc">
{{ steps[step - 1]?.desc }}
</div>
<div
v-if="steps[step - 1]?.warn"
class="warn"
>
<div class="warn-title">
注意
</div>
<div class="warn-text">
{{ steps[step - 1]?.warn }}
</div>
</div>
</div>
</div>
@@ -5,7 +5,9 @@
<template>
<div class="oauth2-demo">
<div class="header">
<div class="title">🔑 OAuth2第三方登录授权码流程</div>
<div class="title">
🔑 OAuth2第三方登录授权码流程
</div>
<div class="subtitle">
用最常见的 Authorization Code Flow建议配合
PKCE默认手动推进不自动下一步
@@ -13,34 +15,64 @@
</div>
<div class="controls">
<button class="btn primary" @click="start" :disabled="step !== 0">
开始
</button>
<button class="btn" @click="prev" :disabled="step <= 1">上一步</button>
<button
class="btn primary"
@click="next"
:disabled="step !== 0"
@click="start"
>
开始
</button>
<button
class="btn"
:disabled="step <= 1"
@click="prev"
>
上一步
</button>
<button
class="btn primary"
:disabled="step === 0 || step >= maxStep"
@click="next"
>
下一步
</button>
<button class="btn" @click="reset">重置</button>
<button class="btn" @click="copy(currentCmd)" :disabled="!currentCmd">
<button
class="btn"
@click="reset"
>
重置
</button>
<button
class="btn"
:disabled="!currentCmd"
@click="copy(currentCmd)"
>
{{ copied ? '已复制' : '复制命令' }}
</button>
</div>
<div v-if="step > 0" class="progress">
<div
v-if="step > 0"
class="progress"
>
Step {{ step }} / {{ maxStep }} · {{ steps[step - 1]?.title }}
</div>
<div class="grid">
<div class="card">
<div class="card-title">角色</div>
<div class="card-title">
角色
</div>
<div class="role">
<div class="pill">Client你的应用</div>
<div class="pill">Authorization Server微信/Google </div>
<div class="pill">Resource Server你的 API</div>
<div class="pill">
Client你的应用
</div>
<div class="pill">
Authorization Server微信/Google
</div>
<div class="pill">
Resource Server你的 API
</div>
</div>
<div class="desc">
OAuth2
@@ -49,17 +81,30 @@
</div>
<div class="card">
<div class="card-title">本步要做什么</div>
<div class="desc">{{ steps[step - 1]?.desc || '点击开始' }}</div>
<div v-if="steps[step - 1]?.warn" class="warn">
<div class="warn-title">注意</div>
<div class="warn-text">{{ steps[step - 1]?.warn }}</div>
<div class="card-title">
本步要做什么
</div>
<div class="desc">
{{ steps[step - 1]?.desc || '点击开始' }}
</div>
<div
v-if="steps[step - 1]?.warn"
class="warn"
>
<div class="warn-title">
注意
</div>
<div class="warn-text">
{{ steps[step - 1]?.warn }}
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-title">请求/命令示例可照抄</div>
<div class="card-title">
请求/命令示例可照抄
</div>
<pre
class="code"
><code>{{ currentCmd || '(点击开始后显示)' }}</code></pre>
@@ -70,7 +115,9 @@
</div>
<div class="card">
<div class="card-title">你真正需要记住的 4 件事</div>
<div class="card-title">
你真正需要记住的 4 件事
</div>
<ul class="list">
<li>
<strong>redirect_uri 必须白名单</strong>避免被人把 code
@@ -9,7 +9,9 @@
<template>
<div class="password-hashing-demo">
<div class="header">
<div class="title">🔐 密码存储哈希 + + </div>
<div class="title">
🔐 密码存储哈希 + +
</div>
<div class="subtitle">
演示 PBKDF2模拟慢哈希如何抵抗彩虹表/暴力破解真实项目通常选
bcrypt/Argon2
@@ -18,7 +20,9 @@
<div class="grid">
<div class="card">
<div class="card-title">输入</div>
<div class="card-title">
输入
</div>
<label class="label">密码</label>
<input
@@ -27,7 +31,7 @@
class="input"
placeholder="例如:123456"
@input="debouncedRecompute"
/>
>
<div class="row">
<div class="col">
@@ -42,29 +46,43 @@
max="200000"
step="1000"
@input="debouncedRecompute"
/>
<div class="hint">越大越慢暴力破解成本越高但登录也更慢</div>
>
<div class="hint">
越大越慢暴力破解成本越高但登录也更慢
</div>
</div>
</div>
<div class="row">
<label class="toggle">
<input v-model="saltEnabled" type="checkbox" @change="recompute" />
<input
v-model="saltEnabled"
type="checkbox"
@change="recompute"
>
<span>启用盐salt</span>
</label>
<button class="btn" @click="regenSalt" :disabled="!saltEnabled">
<button
class="btn"
:disabled="!saltEnabled"
@click="regenSalt"
>
生成新盐
</button>
</div>
<div class="mono-box">
<div class="mono-label">salt</div>
<div class="mono-label">
salt
</div>
<code class="mono">{{ saltEnabled ? saltHex : '(disabled)' }}</code>
</div>
</div>
<div class="card">
<div class="card-title">输出模拟</div>
<div class="card-title">
输出模拟
</div>
<div class="status">
<span class="badge">Algorithm: PBKDF2-SHA256</span>
@@ -72,12 +90,16 @@
</div>
<div class="mono-box">
<div class="mono-label">derived key (hex)</div>
<div class="mono-label">
derived key (hex)
</div>
<code class="mono">{{ hashHex || '(请输入密码)' }}</code>
</div>
<div class="alert">
<div class="alert-title">结论</div>
<div class="alert-title">
结论
</div>
<div class="alert-text">
不要存明文不要用无盐的快速哈希MD5/SHA1/SHA256 直接 hash 密码
应使用专门的密码哈希/KDF + 并设置合理成本
@@ -92,15 +114,23 @@
</div>
<div class="two">
<div class="mono-box">
<div class="mono-label">salt A</div>
<div class="mono-label">
salt A
</div>
<code class="mono">{{ saltA }}</code>
<div class="mono-label">hash A</div>
<div class="mono-label">
hash A
</div>
<code class="mono">{{ hashA || '-' }}</code>
</div>
<div class="mono-box">
<div class="mono-label">salt B</div>
<div class="mono-label">
salt B
</div>
<code class="mono">{{ saltB }}</code>
<div class="mono-label">hash B</div>
<div class="mono-label">
hash B
</div>
<code class="mono">{{ hashB || '-' }}</code>
</div>
</div>
@@ -5,77 +5,148 @@
<template>
<div class="session-demo">
<div class="header">
<div class="title">🍪 Session + Cookie有状态登录</div>
<div class="title">
🍪 Session + Cookie有状态登录
</div>
<div class="subtitle">
默认手动推进先看清楚状态再进入下一步避免自动下一步误解
</div>
</div>
<div class="controls">
<button class="btn primary" @click="start" :disabled="step !== 0">
开始
</button>
<button class="btn" @click="prev" :disabled="step <= 1">上一步</button>
<button
class="btn primary"
@click="next"
:disabled="step !== 0"
@click="start"
>
开始
</button>
<button
class="btn"
:disabled="step <= 1"
@click="prev"
>
上一步
</button>
<button
class="btn primary"
:disabled="step === 0 || step >= maxStep"
@click="next"
>
下一步
</button>
<button class="btn" @click="reset">重置</button>
<button
class="btn"
@click="reset"
>
重置
</button>
</div>
<div v-if="step > 0" class="progress">
<div
v-if="step > 0"
class="progress"
>
Step {{ step }} / {{ maxStep }} · {{ steps[step - 1]?.title }}
</div>
<div class="grid">
<div class="card">
<div class="card-title">浏览器客户端</div>
<div class="card-title">
浏览器客户端
</div>
<div class="box">
<div class="box-title">Cookie Jar</div>
<div v-if="cookie" class="kv">
<div class="k">session_id</div>
<div class="v mono">{{ cookie }}</div>
<div class="box-title">
Cookie Jar
</div>
<div
v-if="cookie"
class="kv"
>
<div class="k">
session_id
</div>
<div class="v mono">
{{ cookie }}
</div>
</div>
<div
v-else
class="empty"
>
暂无 Cookie
</div>
<div v-else class="empty">暂无 Cookie</div>
</div>
<div class="box">
<div class="box-title">本步请求</div>
<div class="box-title">
本步请求
</div>
<pre class="code"><code>{{ clientRequest }}</code></pre>
</div>
</div>
<div class="card">
<div class="card-title">服务器</div>
<div class="card-title">
服务器
</div>
<div class="box">
<div class="box-title">Session StoreRedis/Memory</div>
<div v-if="session" class="kv">
<div class="k mono">{{ cookie }}</div>
<div class="box-title">
Session StoreRedis/Memory
</div>
<div
v-if="session"
class="kv"
>
<div class="k mono">
{{ cookie }}
</div>
<div class="v">
<div class="row"><span class="muted">user_id</span> 123</div>
<div class="row"><span class="muted">username</span> alice</div>
<div class="row"><span class="muted">role</span> admin</div>
<div class="row">
<span class="muted">user_id</span> 123
</div>
<div class="row">
<span class="muted">username</span> alice
</div>
<div class="row">
<span class="muted">role</span> admin
</div>
</div>
</div>
<div v-else class="empty">暂无 Session</div>
<div
v-else
class="empty"
>
暂无 Session
</div>
</div>
<div class="box">
<div class="box-title">本步响应</div>
<div class="box-title">
本步响应
</div>
<pre class="code"><code>{{ serverResponse }}</code></pre>
</div>
</div>
</div>
<div class="card">
<div class="card-title">{{ steps[step - 1]?.title || '流程说明' }}</div>
<div class="desc">{{ steps[step - 1]?.desc }}</div>
<div v-if="steps[step - 1]?.warn" class="warn">
<div class="warn-title">注意</div>
<div class="warn-text">{{ steps[step - 1]?.warn }}</div>
<div class="card-title">
{{ steps[step - 1]?.title || '流程说明' }}
</div>
<div class="desc">
{{ steps[step - 1]?.desc }}
</div>
<div
v-if="steps[step - 1]?.warn"
class="warn"
>
<div class="warn-title">
注意
</div>
<div class="warn-text">
{{ steps[step - 1]?.warn }}
</div>
</div>
</div>
</div>
@@ -5,7 +5,9 @@
<template>
<div class="session-vs-jwt-demo">
<div class="header">
<div class="title">🧩 Session vs JWT怎么选</div>
<div class="title">
🧩 Session vs JWT怎么选
</div>
<div class="subtitle">
选你的约束条件得到推荐方案并解释原因这比背结论更好用
</div>
@@ -13,7 +15,9 @@
<div class="grid">
<div class="card">
<div class="card-title">你的场景</div>
<div class="card-title">
你的场景
</div>
<label class="label">主要客户端</label>
<div class="row">
@@ -96,30 +100,52 @@
</div>
<div class="card">
<div class="card-title">推荐</div>
<div class="card-title">
推荐
</div>
<div class="recommend">
<div class="pill primary">{{ recommendation.title }}</div>
<div class="desc">{{ recommendation.desc }}</div>
<div class="pill primary">
{{ recommendation.title }}
</div>
<div class="desc">
{{ recommendation.desc }}
</div>
</div>
<div class="box">
<div class="box-title">为什么</div>
<div class="box-title">
为什么
</div>
<ul class="list">
<li v-for="(x, i) in recommendation.reasons" :key="i">{{ x }}</li>
<li
v-for="(x, i) in recommendation.reasons"
:key="i"
>
{{ x }}
</li>
</ul>
</div>
<div class="box">
<div class="box-title">落地建议</div>
<div class="box-title">
落地建议
</div>
<ul class="list">
<li v-for="(x, i) in recommendation.tips" :key="i">{{ x }}</li>
<li
v-for="(x, i) in recommendation.tips"
:key="i"
>
{{ x }}
</li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-title">常见误区</div>
<div class="card-title">
常见误区
</div>
<ul class="list">
<li>
<strong>JWT 更安全</strong>JWT