Browse Source

redis 鉴权数据查询

dev_trial
CODE 1 year ago
parent
commit
7ffc28208e
  1. 224
      code/VideoAccess-VCMP/api/app/lib/middlewares/authenticator.js

224
code/VideoAccess-VCMP/api/app/lib/middlewares/authenticator.js

@ -8,42 +8,42 @@ const util = require('util');
const moment = require('moment'); const moment = require('moment');
class ExcludesUrls { class ExcludesUrls {
constructor(opts) { constructor(opts) {
this.allUrls = undefined; this.allUrls = undefined;
this.reload(opts); this.reload(opts);
} }
sanitizePath (path) { sanitizePath (path) {
if (!path) return '/'; if (!path) return '/';
const p = '/' + path.replace(/^\/+/i, '').replace(/\/+$/, '').replace(/\/{2,}/, '/'); const p = '/' + path.replace(/^\/+/i, '').replace(/\/+$/, '').replace(/\/{2,}/, '/');
return p; return p;
} }
reload (opts) { reload (opts) {
// load all url // load all url
if (!this.allUrls) { if (!this.allUrls) {
this.allUrls = opts; this.allUrls = opts;
let that = this; let that = this;
this.allUrls.forEach(function (url, i, arr) { this.allUrls.forEach(function (url, i, arr) {
if (typeof url === "string") { if (typeof url === "string") {
url = { p: url, o: '*' }; url = { p: url, o: '*' };
arr[i] = url; arr[i] = url;
} }
const keys = []; const keys = [];
let eachPath = url.p; let eachPath = url.p;
url.p = (!eachPath || eachPath === '(.*)' || util.isRegExp(eachPath)) ? eachPath : that.sanitizePath(eachPath); url.p = (!eachPath || eachPath === '(.*)' || util.isRegExp(eachPath)) ? eachPath : that.sanitizePath(eachPath);
url.pregexp = pathToRegexp(eachPath, keys); url.pregexp = pathToRegexp(eachPath, keys);
}); });
} }
} }
isExcluded (path, method) { isExcluded (path, method) {
return this.allUrls.some(function (url) { return this.allUrls.some(function (url) {
return !url.auth return !url.auth
&& url.pregexp.test(path) && url.pregexp.test(path)
&& (url.o === '*' || url.o.indexOf(method) !== -1); && (url.o === '*' || url.o.indexOf(method) !== -1);
}); });
} }
} }
/** /**
@ -53,93 +53,99 @@ class ExcludesUrls {
* @param {*} method 当前request的method * @param {*} method 当前request的method
*/ */
let isPathExcluded = function (opts, path, method) { let isPathExcluded = function (opts, path, method) {
let excludeAll = Boolean(opts.exclude && opts.exclude.length && opts.exclude[0] == '*'); let excludeAll = Boolean(opts.exclude && opts.exclude.length && opts.exclude[0] == '*');
let excludes = null; let excludes = null;
if (!excludeAll) { if (!excludeAll) {
let excludeOpts = opts.exclude || []; let excludeOpts = opts.exclude || [];
excludeOpts.push({ p: '/login', o: 'POST' }); excludeOpts.push({ p: '/login', o: 'POST' });
excludeOpts.push({ p: '/logout', o: 'PUT' }); excludeOpts.push({ p: '/logout', o: 'PUT' });
excludes = new ExcludesUrls(excludeOpts); excludes = new ExcludesUrls(excludeOpts);
} }
let excluded = excludeAll || excludes.isExcluded(path, method); let excluded = excludeAll || excludes.isExcluded(path, method);
return excluded; return excluded;
}; };
let authorizeToken = async function (ctx, token) { let authorizeToken = async function (ctx, token) {
let rslt = null; let rslt = null;
const tokenFormatRegexp = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/g; const tokenFormatRegexp = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/g;
if (token && tokenFormatRegexp.test(token)) { if (token && tokenFormatRegexp.test(token)) {
try { try {
const expired = await ctx.redis.hget(token, 'expired'); // const expired = await ctx.redis.hget(token, 'expired');
if (expired && moment().valueOf() <= moment(expired).valueOf()) { let userInfo = await ctx.redis.get(token);
const userInfo = JSON.parse(await ctx.redis.hget(token, 'userInfo')); if (
rslt = { userInfo
'authorized': userInfo.authorized, // expired && moment().valueOf() <= moment(expired).valueOf()
'resources': (userInfo || {}).resources || [], ) {
}; // const userInfo = JSON.parse(await ctx.redis.hget(token, 'userInfo'));
ctx.fs.api.userId = userInfo.id;
ctx.fs.api.userInfo = userInfo; userInfo = JSON.parse(userInfo);
ctx.fs.api.token = token; rslt = {
} 'authorized': userInfo.authorized,
} catch (err) { 'resources': (userInfo || {}).resources || [],
console.log(11111111111,err); };
const { error } = err.response || {}; ctx.fs.api.userId = userInfo.id;
ctx.fs.logger.log('[anxinyun]', '[AUTH] failed', (error || {}).message || `cannot GET /users/${token}`); ctx.fs.api.userInfo = userInfo;
} ctx.fs.api.token = token;
} }
return rslt; } catch (err) {
console.error(err);
const { error } = err.response || {};
ctx.fs.logger.log('[anxinyun]', '[AUTH] failed', (error || {}).message || `cannot GET /users/${token}`);
}
}
return rslt;
}; };
let isResourceAvailable = function (resources, options) { let isResourceAvailable = function (resources, options) {
let authCode = null; let authCode = null;
// authorize user by authorization attribute // authorize user by authorization attribute
const { authAttr, method, path } = options; const { authAttr, method, path } = options;
for (let prop in authAttr) { for (let prop in authAttr) {
let keys = []; let keys = [];
let re = pathToRegexp(prop.replace(/\:[A-Za-z_\-]+\b/g, '(\\d+)'), keys); let re = pathToRegexp(prop.replace(/\:[A-Za-z_\-]+\b/g, '(\\d+)'), keys);
if (re.test(`${method}${path}`)) { if (re.test(`${method}${path}`)) {
authCode = authAttr[prop]; authCode = authAttr[prop];
break; break;
} }
} }
return !authCode || (resources || []).some(code => code === authCode); return !authCode || (resources || []).some(code => code === authCode);
}; };
function factory (app, opts) { function factory (app, opts) {
return async function auth (ctx, next) { return async function auth (ctx, next) {
const { path, method, header, query } = ctx; const { path, method, header, query } = ctx;
ctx.fs.logger.log('[AUTH] start', path, method); ctx.fs.logger.log('[AUTH] start', path, method);
ctx.fs.api = ctx.fs.api || {}; ctx.fs.api = ctx.fs.api || {};
ctx.fs.port = opts.port; ctx.fs.port = opts.port;
ctx.redis = app.redis; ctx.redis = app.redis;
ctx.redisTools = app.redisTools; ctx.redisTools = app.redisTools;
let error = null; let error = null;
if (path) { if (path) {
if (!isPathExcluded(opts, path, method)) { if (!isPathExcluded(opts, path, method)) {
const user = await authorizeToken(ctx, header.token || query.token); const user = await authorizeToken(ctx, header.token || query.token);
if (user && user.authorized) { if (user && user.authorized) {
// if (!isResourceAvailable(user.resources, { authAttr: app.fs.auth.authAttr, path, method })) { // if (!isResourceAvailable(user.resources, { authAttr: app.fs.auth.authAttr, path, method })) {
// error = { status: 403, name: 'Forbidden' } // error = { status: 403, name: 'Forbidden' }
// } else { // } else {
// error = { status: 401, name: 'Unauthorized' } // error = { status: 401, name: 'Unauthorized' }
// } // }
} else { } else {
error = { status: 401, name: 'Unauthorized' } error = { status: 401, name: 'Unauthorized' }
}
} }
} else { }
error = { status: 401, name: 'Unauthorized' }; } else {
} error = { status: 401, name: 'Unauthorized' };
if (error) { }
ctx.fs.logger.log('[AUTH] failed', path, method); if (error) {
ctx.status = error.status; ctx.fs.logger.log('[AUTH] failed', path, method);
ctx.body = error.name; ctx.status = error.status;
} else { ctx.body = error.name;
ctx.fs.logger.log('[AUTH] passed', path, method); } else {
await next(); ctx.fs.logger.log('[AUTH] passed', path, method);
} await next();
} }
}
} }
module.exports = factory; module.exports = factory;

Loading…
Cancel
Save