更换socket鉴权方式

This commit is contained in:
undefined committed 2020-07-31 17:47:42 +08:00
1 parent 8bb389eedd
commit b9076cd5d3
7 files changed
+61 -59

No files matched your search

+1 -4
View File
@@ -62,10 +62,7 @@ class DiscussionHandler extends Handler {
// TODO(twd2): exclude problem/contest discussions? // TODO(twd2): exclude problem/contest discussions?
// TODO(iceboy): continuation based pagination. // TODO(iceboy): continuation based pagination.
if (ObjectID.isValid(name)) name = new ObjectID(name); if (ObjectID.isValid(name)) name = new ObjectID(name);
this.vnode = await discussion.getVnode(domainId, { this.vnode = await discussion.getVnode(domainId, typeMapper[type], name, this);
parentType: typeMapper[type],
parentId: name,
}, this);
if (this.ddoc) { if (this.ddoc) {
this.ddoc.parentType = this.ddoc.parentType || this.vnode.type; this.ddoc.parentType = this.ddoc.parentType || this.vnode.type;
this.ddoc.parentId = this.ddoc.parentId || this.vnode.id; this.ddoc.parentId = this.ddoc.parentId || this.vnode.id;
-7
View File
@@ -102,12 +102,6 @@ class SwitchLanguageHandler extends Handler {
} }
} }
class SockToken extends Handler {
async get() {
this.response.body = { token: this.UIContext.token };
}
}
class UiSettingsHandler extends Handler { class UiSettingsHandler extends Handler {
async get() { async get() {
const [ const [
@@ -143,7 +137,6 @@ export async function apply() {
Route('status', '/status', StatusHandler); Route('status', '/status', StatusHandler);
Route('status_update', '/status/update', StatusUpdateHandler); Route('status_update', '/status/update', StatusUpdateHandler);
Route('switch_language', '/language/:lang', SwitchLanguageHandler); Route('switch_language', '/language/:lang', SwitchLanguageHandler);
Route('token', '/token', SockToken);
Route('ui', '/extra.css', UiSettingsHandler); Route('ui', '/extra.css', UiSettingsHandler);
} }
+19 -19
View File
@@ -158,33 +158,33 @@ export function getNode(domainId: string, _id: string) {
return document.get(domainId, document.TYPE_DISCUSSION_NODE, _id); return document.get(domainId, document.TYPE_DISCUSSION_NODE, _id);
} }
export async function getVnode(domainId: string, ddoc: any, handler: any) { export async function getVnode(domainId: string, type: number, id: string, handler: any) {
if (ddoc.parentType === document.TYPE_PROBLEM) { if (type === document.TYPE_PROBLEM) {
const pdoc = await problem.get(domainId, ddoc.parentId); const pdoc = await problem.get(domainId, id);
if (!pdoc) return null; if (!pdoc) return null;
if (pdoc.hidden && handler) handler.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN); if (pdoc.hidden && handler) handler.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN);
return { ...pdoc, type: ddoc.parentType, id: ddoc.parentId }; return { ...pdoc, type, id };
} }
if (ddoc.parentType === document.TYPE_CONTEST) { if (type === document.TYPE_CONTEST) {
const tdoc = await contest.get(domainId, ddoc.parentId); const tdoc = await contest.get(domainId, new ObjectID(id));
return { ...tdoc, type: ddoc.parentType, id: ddoc.parentId }; return { ...tdoc, type, id };
} }
if (ddoc.parentType === document.TYPE_DISCUSSION_NODE) { if (type === document.TYPE_DISCUSSION_NODE) {
const ndoc = await getNode(domainId, ddoc.parentId); const ndoc = await getNode(domainId, id);
return { return {
...ndoc, ...ndoc,
title: ddoc.parentId, title: id,
type: ddoc.parentType, type,
id: ddoc.parentId, id,
}; };
} }
if (ddoc.parentType === document.TYPE_TRAINING) { if (type === document.TYPE_TRAINING) {
const tdoc = await training.get(domainId, ddoc.parentId); const tdoc = await training.get(domainId, id);
return { ...tdoc, type: ddoc.parentType, id: ddoc.parentId }; return { ...tdoc, type, id };
} }
if (ddoc.parentType === document.TYPE_HOMEWORK) { if (type === document.TYPE_HOMEWORK) {
const tdoc = await contest.get(domainId, ddoc.parentId, document.TYPE_HOMEWORK); const tdoc = await contest.get(domainId, new ObjectID(id), document.TYPE_HOMEWORK);
return { ...tdoc, type: ddoc.parentType, id: ddoc.parentId }; return { ...tdoc, type, id };
} }
return { return {
title: 'Missing Node', title: 'Missing Node',
@@ -201,7 +201,7 @@ export async function getListVnodes(domainId: string, ddocs: any, handler: any)
const tasks = []; const tasks = [];
const res = {}; const res = {};
async function task(ddoc) { async function task(ddoc) {
const vnode = await getVnode(domainId, ddoc, handler); const vnode = await getVnode(domainId, ddoc.parentType, ddoc.parentId, handler);
if (!res[ddoc.parentType]) res[ddoc.parentType] = {}; if (!res[ddoc.parentType]) res[ddoc.parentType] = {};
res[ddoc.parentType][ddoc.parentId] = vnode; res[ddoc.parentType][ddoc.parentId] = vnode;
} }
-2
View File
@@ -4,7 +4,6 @@ import * as db from '../service/db';
const coll = db.collection('token'); const coll = db.collection('token');
export const TYPE_SESSION = 0; export const TYPE_SESSION = 0;
export const TYPE_TOKEN = 1;
export const TYPE_REGISTRATION = 2; export const TYPE_REGISTRATION = 2;
export const TYPE_CHANGEMAIL = 3; export const TYPE_CHANGEMAIL = 3;
export const TYPE_OAUTH = 4; export const TYPE_OAUTH = 4;
@@ -90,7 +89,6 @@ global.Hydro.postInit.push(ensureIndexes);
global.Hydro.model.token = { global.Hydro.model.token = {
TYPE_SESSION, TYPE_SESSION,
TYPE_CHANGEMAIL, TYPE_CHANGEMAIL,
TYPE_TOKEN,
TYPE_OAUTH, TYPE_OAUTH,
TYPE_REGISTRATION, TYPE_REGISTRATION,
TYPE_LOSTPASS, TYPE_LOSTPASS,
+38 -25
View File
@@ -12,6 +12,7 @@ import Body from 'koa-body';
import Router from 'koa-router'; import Router from 'koa-router';
import cache from 'koa-static-cache'; import cache from 'koa-static-cache';
import sockjs from 'sockjs'; import sockjs from 'sockjs';
import { SetOption } from 'cookies';
import serialize, { SerializeJSOptions } from 'serialize-javascript'; import serialize, { SerializeJSOptions } from 'serialize-javascript';
import { argv } from 'yargs'; import { argv } from 'yargs';
import { lrucache } from '../utils'; import { lrucache } from '../utils';
@@ -365,28 +366,14 @@ export class Handler {
]); ]);
if (!this.domain) { if (!this.domain) {
this.args.domainId = 'system'; this.args.domainId = 'system';
[this.user, this.UIContext.token] = await Promise.all([ this.user = await user.getById('system', this.session.uid);
user.getById('system', this.session.uid), if (!this.user) this.user = await user.getById('system', 0);
token.createOrUpdate(
token.TYPE_TOKEN, 600, { uid: this.session.uid, domainId },
),
]);
throw new NotFoundError(domainId); throw new NotFoundError(domainId);
} }
[this.user, this.UIContext.token] = await Promise.all([ this.user = await user.getById(domainId, this.session.uid);
user.getById(domainId, this.session.uid),
token.createOrUpdate(
token.TYPE_TOKEN, 600, { uid: this.session.uid, domainId },
),
]);
if (!this.user) { if (!this.user) {
this.session.uid = 0; this.session.uid = 0;
[this.user, this.UIContext.token] = await Promise.all([ this.user = await user.getById(domainId, this.session.uid);
user.getById(domainId, this.session.uid),
token.createOrUpdate(
token.TYPE_TOKEN, 600, { uid: this.session.uid, domainId },
),
]);
} }
this.csrfToken = this.getCsrfToken(this.session._id || String.random(32)); this.csrfToken = this.getCsrfToken(this.session._id || String.random(32));
this.UIContext.csrfToken = this.csrfToken; this.UIContext.csrfToken = this.csrfToken;
@@ -484,7 +471,10 @@ export class Handler {
}, },
); );
} }
const cookie: any = { secure: await system.get('session.secure') }; const cookie: SetOption = {
secure: await system.get('session.secure'),
httpOnly: false,
};
if (this.session.save) { if (this.session.save) {
cookie.expires = this.session.expireAt; cookie.expires = this.session.expireAt;
cookie.maxAge = expireSeconds; cookie.maxAge = expireSeconds;
@@ -492,7 +482,7 @@ export class Handler {
this.ctx.cookies.set('sid', this.session._id, cookie); this.ctx.cookies.set('sid', this.session._id, cookie);
} }
async onerror(error) { async onerror(error: HydroError) {
if (!error.msg) error.msg = () => error.message; if (!error.msg) error.msg = () => error.message;
console.error(error.msg(), error.params); console.error(error.msg(), error.params);
console.error(error.stack); console.error(error.stack);
@@ -600,6 +590,8 @@ export class ConnectionHandler {
user: any user: any
domain: DomainDoc
constructor(conn: sockjs.Connection) { constructor(conn: sockjs.Connection) {
this.conn = conn; this.conn = conn;
this.request = { this.request = {
@@ -683,10 +675,24 @@ export class ConnectionHandler {
this.close(1001, err.toString()); this.close(1001, err.toString());
} }
async init({ domainId }) { async getSession(cookieHeader: string) {
this.session = await token.get(this.request.params.token, token.TYPE_TOKEN); const cookies: any = {};
this.session = this.session || { uid: 0, domainId: 'system' }; const ref = cookieHeader.split(';');
this.args.domainId = this.session.domainId; for (let j = 0; j < ref.length; j++) {
const cookie = ref[j];
const parts = cookie.split('=');
cookies[parts[0].trim()] = (parts[1] || '').trim();
}
this.session = await token.get(cookies.sid || '', token.TYPE_SESSION);
if (!this.session) this.session = { uid: 0, domainId: 'system' };
}
@param('cookie', Types.String)
async init(domainId: string, cookie: string) {
[this.domain] = await Promise.all([
domain.get(domainId),
this.getSession(cookie),
]);
const bdoc = await blacklist.get(this.request.ip); const bdoc = await blacklist.get(this.request.ip);
if (bdoc) throw new BlacklistedError(this.request.ip); if (bdoc) throw new BlacklistedError(this.request.ip);
this.user = await user.getById(domainId, this.session.uid); this.user = await user.getById(domainId, this.session.uid);
@@ -699,14 +705,21 @@ export function Connection(
RouteConnHandler: any, RouteConnHandler: any,
...permPrivChecker: Array<number | bigint | Function> ...permPrivChecker: Array<number | bigint | Function>
) { ) {
const sock = sockjs.createServer({ prefix }); const sock = sockjs.createServer({ prefix, log: (a, b) => console.log(a, b) });
const checker = Checker(permPrivChecker); const checker = Checker(permPrivChecker);
sock.on('connection', async (conn) => { sock.on('connection', async (conn) => {
const h: Dictionary<any> = new RouteConnHandler(conn); const h: Dictionary<any> = new RouteConnHandler(conn);
try { try {
const args = { domainId: 'system', ...h.request.params }; const args = { domainId: 'system', ...h.request.params };
h.args = args; h.args = args;
const cookie = await new Promise((resolve) => {
conn.once('data', (c) => {
resolve(c);
});
});
args.cookie = cookie;
await h.init(args); await h.init(args);
conn.write(JSON.stringify({ event: 'auth' }));
checker.call(h); checker.call(h);
if (h._prepare) await h._prepare(args); if (h._prepare) await h._prepare(args);
+2 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.11.2", "version": "2.11.3",
"main": "dist/loader.js", "main": "dist/loader.js",
"bin": "bin/hydrooj.js", "bin": "bin/hydrooj.js",
"repository": "https://github.com/hydro-dev/Hydro.git", "repository": "https://github.com/hydro-dev/Hydro.git",
@@ -12,6 +12,7 @@
"dependencies": { "dependencies": {
"adm-zip": "^0.4.16", "adm-zip": "^0.4.16",
"ansi_up": "^4.0.4", "ansi_up": "^4.0.4",
"cookies": "^0.8.0",
"detect-browser": "^5.1.1", "detect-browser": "^5.1.1",
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"html-to-text": "^5.1.1", "html-to-text": "^5.1.1",
+1 -1
View File
@@ -759,7 +759,7 @@ cookiejar@^2.1.2:
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c"
integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==
cookies@~0.8.0: cookies@^0.8.0, cookies@~0.8.0:
version "0.8.0" version "0.8.0"
resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90" resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90"
integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow== integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==