IOT线 鉴权系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

171 lines
4.7 KiB

'use strict';
// ! OAUTH2.0 模式
const uuid = require('uuid');
const moment = require('moment');
// 暂时定制予 vcmp 视频平台 app
async function apply (ctx) {
try {
const { models } = ctx.fs.dc;
const { body } = ctx.request;
const { authorization } = ctx.headers;
const { utils: { oauthParseAuthHeader, oauthParseBody } } = ctx.app.fs
await oauthParseBody(body, 'apply');
const keySplit = await oauthParseAuthHeader(authorization);
// TODO 删除此应用下的其他 token
// 记录token
const userInfo = {
appKey: keySplit[0],
appSecret: keySplit[1]
}
const token = uuid.v4();
const expired = moment().add(1, 'year');
await models.UserToken.create({
token: token,
userInfo: userInfo,
expired: expired.format('YYYY-MM-DD HH:mm:ss')
});
ctx.status = 200;
ctx.body = {
token: token,
expires: expired.toISOString()
};
} catch (e) {
ctx.status = 400;
ctx.body = {
name: 'RequestError',
message: e.message
};
}
}
async function refresh (ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { authorization } = ctx.headers;
const { body } = ctx.request;
const { models } = ctx.fs.dc;
const { utils: { oauthParseAuthHeader, oauthParseBody } } = ctx.app.fs
const keySplit = await oauthParseAuthHeader(authorization);
const $token = await oauthParseBody(body, 'refresh');
const oldToken = await models.UserToken.findOne({
where: {
token: $token,
expired: { $gte: moment().format('YYYY-MM-DD HH:mm:ss') }
}
});
if (
!oldToken
|| oldToken.userInfo.appKey != keySplit[0]
|| oldToken.userInfo.appSecret != keySplit[1]
) {
throw new Error('参数无效:正文token无效或已过期,请重新申请');
}
const token = uuid.v4();
const expired = moment().add(1, 'year');
// 记录token
const tokenMsg = {
token: token,
userInfo: oldToken.userInfo,
expired: expired.format('YYYY-MM-DD HH:mm:ss')
}
await models.UserToken.create(tokenMsg, { transaction });
await ctx.redis.hmset(token, tokenMsg);
// 移除旧的token
await models.UserToken.destroy({ where: { token: $token }, transaction });
await ctx.redisTools.hdelall($token);
await transaction.commit();
ctx.status = 200;
ctx.body = {
token: token,
expires: expired.toISOString()
};
} catch (e) {
await transaction.rollback();
ctx.status = 400;
ctx.body = {
name: 'RequestError',
message: e.message
};
}
}
async function invalidate (ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { models } = ctx.fs.dc;
const { body } = ctx.request;
const { authorization } = ctx.headers;
const { utils: { oauthParseAuthHeader, oauthParseBody } } = ctx.app.fs
const keySplit = await oauthParseAuthHeader(authorization);
const $token = await oauthParseBody(body, 'invalidate');
// 删除token
await models.UserToken.destroy({ where: { token: $token } });
await ctx.redisTools.hdelall($token);
await transaction.commit();
ctx.status = 204;
} catch (e) {
await transaction.rollback();
ctx.status = 400;
ctx.body = {
name: 'RequestError',
message: e.message
};
}
}
async function invalidateAll (ctx) {
// 给其他系统删除token
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { models } = ctx.fs.dc;
const { appKey } = ctx.query;
const tokenRes = await models.UserToken.findAll({
where: {
'userInfo.appKey': appKey
}
})
// 删除token
await models.UserToken.destroy({
where: { 'userInfo.appKey': appKey },
transaction
});
tokenRes.forEach(async t => {
await ctx.redisTools.hdelall(t.token);
})
await transaction.commit();
ctx.status = 204;
} catch (e) {
await transaction.rollback();
ctx.status = 400;
ctx.body = {
name: 'RequestError',
message: e.message
};
}
}
// OAUTH2.0 END
module.exports = {
apply,
refresh,
invalidate,
invalidateAll, // 给其他系统删除token
}