From f48b91dc0a50792b7d83cad16452d692d815cf59 Mon Sep 17 00:00:00 2001 From: hanhh <18330117883@163.com> Date: Fri, 24 Sep 2021 22:24:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A4=9A=E7=AB=AF=E7=99=BB?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/config/util.ts | 37 ++++++++++++++++++++++++++++++++++++- back/loaders/express.ts | 25 +++++++++++++++++++++---- back/services/auth.ts | 18 +++++++++++++++--- shell/task.sh | 9 +++------ typings.d.ts | 14 +++++++++++--- 5 files changed, 86 insertions(+), 17 deletions(-) diff --git a/back/config/util.ts b/back/config/util.ts index 232c4d9a..e8847886 100644 --- a/back/config/util.ts +++ b/back/config/util.ts @@ -117,7 +117,9 @@ export function createRandomString(min: number, max: number): string { export function getToken(req: any) { const { authorization } = req.headers; if (authorization && authorization.split(' ')[0] === 'Bearer') { - return authorization.split(' ')[1]; + return (authorization.split(' ')[1] as string) + .replace('mobile-', '') + .replace('desktop-', ''); } return ''; } @@ -184,3 +186,36 @@ export async function getNetIp(req: any) { return { address: `获取失败`, ip }; } } + +export function getPlatform(userAgent: string): 'mobile' | 'desktop' { + const ua = userAgent.toLowerCase(); + const testUa = (regexp: RegExp) => regexp.test(ua); + const testVs = (regexp: RegExp) => + (ua.match(regexp) || []) + .toString() + .replace(/[^0-9|_.]/g, '') + .replace(/_/g, '.'); + + // 系统 + let system = 'unknow'; + if (testUa(/windows|win32|win64|wow32|wow64/g)) { + system = 'windows'; // windows系统 + } else if (testUa(/macintosh|macintel/g)) { + system = 'macos'; // macos系统 + } else if (testUa(/x11/g)) { + system = 'linux'; // linux系统 + } else if (testUa(/android|adr/g)) { + system = 'android'; // android系统 + } else if (testUa(/ios|iphone|ipad|ipod|iwatch/g)) { + system = 'ios'; // ios系统 + } + + let platform = 'desktop'; + if (system === 'windows' || system === 'macos' || system === 'linux') { + platform = 'desktop'; + } else if (system === 'android' || system === 'ios' || testUa(/mobile/g)) { + platform = 'mobile'; + } + + return platform as 'mobile' | 'desktop'; +} diff --git a/back/loaders/express.ts b/back/loaders/express.ts index 87eaf48d..bd34d83c 100644 --- a/back/loaders/express.ts +++ b/back/loaders/express.ts @@ -5,7 +5,7 @@ import routes from '../api'; import config from '../config'; import jwt from 'express-jwt'; import fs from 'fs'; -import { getToken } from '../config/util'; +import { getPlatform, getToken } from '../config/util'; import Container from 'typedi'; import OpenService from '../services/open'; import rewrite from 'express-urlrewrite'; @@ -17,7 +17,10 @@ export default ({ app }: { app: Application }) => { app.use(bodyParser.json({ limit: '50mb' })); app.use(bodyParser.urlencoded({ limit: '50mb', extended: true })); app.use( - jwt({ secret: config.secret as string, algorithms: ['HS384'] }).unless({ + jwt({ + secret: config.secret as string, + algorithms: ['HS384'], + }).unless({ path: [ '/api/login', '/api/crons/status', @@ -27,6 +30,16 @@ export default ({ app }: { app: Application }) => { }), ); + app.use((req: Request, res, next) => { + if (!req.headers) { + req.platform = 'desktop'; + } else { + const platform = getPlatform(req.headers['user-agent'] || ''); + req.platform = platform; + } + return next(); + }); + app.use(async (req, res, next) => { const headerToken = getToken(req); if (req.path.startsWith('/open/')) { @@ -66,8 +79,12 @@ export default ({ app }: { app: Application }) => { const data = fs.readFileSync(config.authConfigFile, 'utf8'); if (data) { - const { token } = JSON.parse(data); - if (token && headerToken === token) { + const { token = '', tokens = {} } = JSON.parse(data); + console.log(tokens); + console.log(req.platform); + console.log(tokens[req.platform]); + if (headerToken === token || tokens[req.platform] === headerToken) { + console.log('yes'); return next(); } } diff --git a/back/services/auth.ts b/back/services/auth.ts index d3886565..04a910b2 100644 --- a/back/services/auth.ts +++ b/back/services/auth.ts @@ -1,6 +1,6 @@ import { Service, Inject } from 'typedi'; import winston from 'winston'; -import { createRandomString, getNetIp } from '../config/util'; +import { createRandomString, getNetIp, getPlatform } from '../config/util'; import config from '../config'; import * as fs from 'fs'; import _ from 'lodash'; @@ -29,7 +29,7 @@ export default class AuthService { username: string; password: string; }, - req: any, + req: Request, needTwoFactor = true, ): Promise { if (!fs.existsSync(config.authConfigFile)) { @@ -49,6 +49,7 @@ export default class AuthService { lastaddr, twoFactorActivated, twoFactorActived, + tokens = {}, } = content; // patch old field twoFactorActivated = twoFactorActivated || twoFactorActived; @@ -94,6 +95,10 @@ export default class AuthService { this.updateAuthInfo(content, { token, + tokens: { + ...tokens, + [req.platform]: token, + }, lastlogon: timestamp, retries: 0, lastip: ip, @@ -214,7 +219,14 @@ export default class AuthService { return isValid; } - public async twoFactorLogin({ username, password, code }, req) { + public async twoFactorLogin( + { + username, + password, + code, + }: { username: string; password: string; code: string }, + req: any, + ) { const authInfo = this.getAuthInfo(); const { isTwoFactorChecking, twoFactorSecret } = authInfo; if (!isTwoFactorChecking) { diff --git a/shell/task.sh b/shell/task.sh index ac67ea10..28a4e17b 100755 --- a/shell/task.sh +++ b/shell/task.sh @@ -167,7 +167,7 @@ run_concurrent() { run_designated() { local file_param="$1" local env_param="$2" - local num_param="$3" + local num_param=$(echo "$3" | perl -pe "s|.*$2 (.*)|\1|") if [[ ! $env_param ]] || [[ ! $num_param ]]; then echo -e "\n 缺少单独运行的参数 task xxx.js single Test 1" exit 1 @@ -268,7 +268,7 @@ main() { 1) run_normal "$1" ;; - 2 | 3 | 4) + *) case $2 in now) run_normal "$1" "$2" @@ -277,16 +277,13 @@ main() { run_concurrent "$1" "$3" ;; desi) - run_designated "$1" "$3" "$4" + run_designated "$1" "$3" "$*" ;; *) run_else "$@" ;; esac ;; - *) - run_else "$@" - ;; esac [[ -f $log_path ]] && cat $log_path elif [[ $# -eq 0 ]]; then diff --git a/typings.d.ts b/typings.d.ts index 4b2efc88..e1244ee2 100644 --- a/typings.d.ts +++ b/typings.d.ts @@ -2,7 +2,15 @@ declare module '*.css'; declare module '*.less'; declare module '*.png'; declare module '*.svg' { - export function ReactComponent(props: React.SVGProps): React.ReactElement - const url: string - export default url + export function ReactComponent( + props: React.SVGProps, + ): React.ReactElement; + const url: string; + export default url; +} + +declare namespace Express { + export interface Request { + platform: 'desktop' | 'mobile'; + } }