登录改用访问令牌 + 刷新令牌,不用 cookie
- 访问令牌:JWT(HS256),15 分钟,Authorization: Bearer;WebSocket 放在网址参数里 - 刷新令牌:30 天,每次刷新换新的,数据库只存哈希;退出登录即作废 - 重置密码、删除学生:令牌版本加一并删除刷新令牌,所有设备立即退出 - 签名密钥首次使用时生成,存在数据库 settings 表 - 浏览器:令牌存 localStorage;快过期先刷新,401 时刷新一次再重试;多个标签页同时刷新不冲突 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a3eb563b70
commit
5bb2940969
11 files changed
+332
-110
No files matched your search
+19
-14
@@ -1,4 +1,5 @@
|
||||
import { reactive, shallowReactive } from 'vue'
|
||||
import { validAccessToken } from '../tokens'
|
||||
import type {
|
||||
BoardState,
|
||||
ClientMessage,
|
||||
@@ -43,20 +44,24 @@ export function createRunSession() {
|
||||
let actionSentAt = 0
|
||||
|
||||
function connect() {
|
||||
connecting ??= new Promise<void>((resolve) => {
|
||||
const protocol = location.protocol === 'https:' ? 'wss' : 'ws'
|
||||
const ws = new WebSocket(`${protocol}://${location.host}/ws`)
|
||||
socket = ws
|
||||
ws.onmessage = (event) => handle(JSON.parse(event.data) as ServerMessage)
|
||||
ws.onopen = () => resolve()
|
||||
ws.onclose = () => {
|
||||
state.status = 'stopped'
|
||||
state.board = null
|
||||
socket = undefined
|
||||
connecting = undefined
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
connecting ??= validAccessToken().then(
|
||||
(token) =>
|
||||
new Promise<void>((resolve) => {
|
||||
const protocol = location.protocol === 'https:' ? 'wss' : 'ws'
|
||||
// 浏览器的 WebSocket 不能带请求头,访问令牌放在网址参数里(只在建立连接时检查)
|
||||
const ws = new WebSocket(`${protocol}://${location.host}/ws?token=${encodeURIComponent(token ?? '')}`)
|
||||
socket = ws
|
||||
ws.onmessage = (event) => handle(JSON.parse(event.data) as ServerMessage)
|
||||
ws.onopen = () => resolve()
|
||||
ws.onclose = () => {
|
||||
state.status = 'stopped'
|
||||
state.board = null
|
||||
socket = undefined
|
||||
connecting = undefined
|
||||
resolve()
|
||||
}
|
||||
}),
|
||||
)
|
||||
return connecting
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user