333 lines
13 KiB
JavaScript
333 lines
13 KiB
JavaScript
|
|
'use strict';
|
||
|
|
|
||
|
|
// const sha256 = require("crypto-js/sha256");
|
||
|
|
|
||
|
|
module.exports = () => {
|
||
|
|
class Model {
|
||
|
|
constructor(ctx) {
|
||
|
|
this.ctx = ctx;
|
||
|
|
this.fileName = "oauth";
|
||
|
|
this.redisType = {
|
||
|
|
"B": "db0",
|
||
|
|
"C": "db1",
|
||
|
|
"M": "db2",
|
||
|
|
"T": "db5",
|
||
|
|
"E": "db6",
|
||
|
|
"A": "db7"
|
||
|
|
};
|
||
|
|
this.modelType = {
|
||
|
|
"B": this.ctx.model.BSide,
|
||
|
|
"C": this.ctx.model2.CSide,
|
||
|
|
"M": this.ctx.model3.Insiders,
|
||
|
|
"T": this.ctx.model4.Account,
|
||
|
|
"E": this.ctx.model5.Examinee,
|
||
|
|
"A": this.ctx.model5.Manager,
|
||
|
|
};
|
||
|
|
this.redisAccessTokenEX = {
|
||
|
|
"B": 1000,
|
||
|
|
"C": 1000,
|
||
|
|
"M": 1000,
|
||
|
|
"T": 1000,
|
||
|
|
"E": 3000,
|
||
|
|
"A": 1000
|
||
|
|
};
|
||
|
|
this.redisRefreshTokenEX = {
|
||
|
|
"B": 1000,
|
||
|
|
"C": 1000,
|
||
|
|
"M": 1000,
|
||
|
|
"T": 1000,
|
||
|
|
"E": 360000,
|
||
|
|
"A": 1000
|
||
|
|
};
|
||
|
|
}
|
||
|
|
async getClient(clientId) {
|
||
|
|
// let clientSecret = this.ctx.request.body.client_secret;
|
||
|
|
try {
|
||
|
|
// 1. 从数据库中查询客户端信息
|
||
|
|
// if(clientId == "insiders-manager" && clientSecret == "insiders-manager") {
|
||
|
|
let checkFixedClient = false;
|
||
|
|
this.ctx.app.config.fixedClient.forEach(element => {
|
||
|
|
if (clientId == element) checkFixedClient = true;
|
||
|
|
});
|
||
|
|
if (checkFixedClient) {
|
||
|
|
return {
|
||
|
|
id: clientId,
|
||
|
|
redirectUris: 'http://127.0.0.1:'+this.ctx.app.server.address().port+'/getToken/',
|
||
|
|
grants: ['authorization_code'],
|
||
|
|
type: clientId,
|
||
|
|
};
|
||
|
|
} else {
|
||
|
|
const client = await this.ctx.model3.Business.findOne({ where: { client_id: clientId } });
|
||
|
|
if (!client) return false;
|
||
|
|
|
||
|
|
// 2. 校验客户端密钥
|
||
|
|
// if (clientSecret && (clientSecret !== client.client_secret)) {
|
||
|
|
// return false;
|
||
|
|
// }
|
||
|
|
// 3. 返回数据
|
||
|
|
return {
|
||
|
|
id: client.client_id,
|
||
|
|
redirectUris: 'http://127.0.0.1:'+this.ctx.app.server.address().port+'/getToken/',
|
||
|
|
grants: ['authorization_code'],
|
||
|
|
type: client.type,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
const blockName = this.fileName + "--" + "getClient";
|
||
|
|
this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
async grantTypeAllowed (clientId, grantType) {
|
||
|
|
try {
|
||
|
|
const client = await this.ctx.model.Oauth2.findOne({ where: { clientId: clientId } });
|
||
|
|
if(clientId == client.clientId && grantType == client.grants.split(',')){
|
||
|
|
return true;
|
||
|
|
}else{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
const blockName = this.fileName + "--" + "grantTypeAllowed";
|
||
|
|
this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
async getUser(username, password) {
|
||
|
|
try {
|
||
|
|
// 返回用户信息
|
||
|
|
return {
|
||
|
|
uid: username,
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
const blockName = this.fileName + "--" + "getUser";
|
||
|
|
this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
async getUserFromClient (clientId) {
|
||
|
|
try {
|
||
|
|
return {
|
||
|
|
uid:clientId.id
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
const blockName = this.fileName + "--" + "getUserFromClient";
|
||
|
|
this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
async saveToken(token, client, user) {
|
||
|
|
try {
|
||
|
|
const rdmtoken = {
|
||
|
|
accessToken: token.accessToken,
|
||
|
|
refreshToken: token.refreshToken,
|
||
|
|
clientId: client.id,
|
||
|
|
};
|
||
|
|
const lastCode = user.uid[user.uid.length-1];
|
||
|
|
const redisDbType = this.redisType[lastCode];
|
||
|
|
const redisAccessTokenEX = this.redisAccessTokenEX[lastCode];
|
||
|
|
const redisRefreshTokenEX = this.redisRefreshTokenEX[lastCode];
|
||
|
|
let reex = ((new Date(token.refreshTokenExpiresAt).getTime() - new Date().getTime()) / redisRefreshTokenEX).toFixed(0);
|
||
|
|
const usertoken = await this.ctx.app.redis.get(redisDbType).get(user.uid);
|
||
|
|
if(usertoken){
|
||
|
|
await this.ctx.app.redis.get(redisDbType).del(JSON.parse(usertoken).accessToken);
|
||
|
|
let remainder = await this.ctx.app.redis.get(redisDbType).ttl(user.uid);
|
||
|
|
reex = remainder;
|
||
|
|
await this.ctx.app.redis.get(redisDbType).del(JSON.parse(usertoken).refreshToken);
|
||
|
|
}
|
||
|
|
await this.ctx.app.redis.get(redisDbType).set(user.uid, JSON.stringify(rdmtoken), 'EX', reex);
|
||
|
|
// 1.保存访问令牌
|
||
|
|
const rdmaccess = {
|
||
|
|
token: token.accessToken,
|
||
|
|
expiresAt: token.accessTokenExpiresAt,
|
||
|
|
scope: token.scope || '',
|
||
|
|
clientId: client.id,
|
||
|
|
clientType: client.type,
|
||
|
|
uid: user.uid,
|
||
|
|
};
|
||
|
|
let acex = ((new Date(token.accessTokenExpiresAt).getTime() - new Date().getTime()) / redisAccessTokenEX).toFixed(0);
|
||
|
|
await this.ctx.app.redis.get(redisDbType).set(token.accessToken, JSON.stringify(rdmaccess), 'EX', acex);
|
||
|
|
// 2.保存刷新令牌
|
||
|
|
if(token.refreshToken){
|
||
|
|
const rdmrefresh = {
|
||
|
|
token: token.refreshToken,
|
||
|
|
expiresAt: token.refreshTokenExpiresAt,
|
||
|
|
scope: token.scope || '',
|
||
|
|
clientId: client.id,
|
||
|
|
clientType: client.type,
|
||
|
|
uid: user.uid,
|
||
|
|
};
|
||
|
|
await this.ctx.app.redis.get(redisDbType).set(token.refreshToken, JSON.stringify(rdmrefresh), 'EX', reex);
|
||
|
|
}
|
||
|
|
// 3.返回保存的令牌信息
|
||
|
|
return {
|
||
|
|
accessToken: { uid: user.uid, token:token.accessToken },
|
||
|
|
accessTokenExpiresAt: token.accessTokenExpiresAt,
|
||
|
|
refreshToken: token.refreshToken ? token.refreshToken : '',
|
||
|
|
refreshTokenExpiresAt: token.refreshTokenExpiresAt ? token.refreshTokenExpiresAt : '',
|
||
|
|
scope: token.scope || '',
|
||
|
|
client: { id: client.id, type: client.type },
|
||
|
|
user: { uid: user.uid },
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
const blockName = this.fileName + "--" + "saveToken";
|
||
|
|
this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
async getAccessToken(bearerToken) {
|
||
|
|
try {
|
||
|
|
// 1. 查询数据库,获取访问密钥信息
|
||
|
|
// 2. 查询数据库,获取客户端信息
|
||
|
|
// 3. 查询数据库,获取用户信息
|
||
|
|
let { access_token, uid } = JSON.parse(bearerToken);
|
||
|
|
const lastCode = uid[uid.length-1];
|
||
|
|
const redisDbType = this.redisType[lastCode];
|
||
|
|
const token = await this.ctx.app.redis.get(redisDbType).get(access_token);
|
||
|
|
if (token == null) {
|
||
|
|
const data = await this.ctx.app.redis.get(redisDbType).get(uid);
|
||
|
|
const refreshToken = await this.ctx.app.redis.get(redisDbType).get(JSON.parse(data).refreshToken);
|
||
|
|
if (refreshToken == null) await this.ctx.app.redis.get(redisDbType).del(uid);
|
||
|
|
};
|
||
|
|
|
||
|
|
// 4. 返回数据
|
||
|
|
let accessToken = {
|
||
|
|
accessTokenExpiresAt: new Date(JSON.parse(token).expiresAt),
|
||
|
|
user: { uid: JSON.parse(token).uid },
|
||
|
|
client_type: JSON.parse(token).clientType,
|
||
|
|
}
|
||
|
|
return accessToken;
|
||
|
|
} catch (error) {
|
||
|
|
const blockName = this.fileName + "--" + "getAccessToken";
|
||
|
|
this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
async revokeToken(token) {
|
||
|
|
try {
|
||
|
|
// 查询数据库并删除刷新令牌
|
||
|
|
const revokeValue = await this.ctx.app.redis.del(token.refreshToken);
|
||
|
|
if(revokeValue){
|
||
|
|
return true;
|
||
|
|
}else{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
const blockName = this.fileName + "--" + "revokeToken";
|
||
|
|
this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
async saveAuthorizationCode(code, client, user) {
|
||
|
|
try {
|
||
|
|
// 1. 保存授权码信息到数据库
|
||
|
|
const rdmcode = {
|
||
|
|
code: code.authorizationCode,
|
||
|
|
expiresAt: code.expiresAt,
|
||
|
|
redirectUri: code.redirectUri,
|
||
|
|
scope: code.scope || '',
|
||
|
|
clientId: client.id,
|
||
|
|
clientType: client.type,
|
||
|
|
uid: user.uid
|
||
|
|
}
|
||
|
|
let ex = ((new Date(code.expiresAt).getTime() - new Date().getTime()) / 1000).toFixed(0);
|
||
|
|
await this.ctx.app.redis.get('db3').set(code.authorizationCode, JSON.stringify(rdmcode), 'EX', ex);
|
||
|
|
|
||
|
|
// 2. 返回数据
|
||
|
|
return {
|
||
|
|
authorizationCode: code.authorizationCode,
|
||
|
|
expiresAt: code.expiresAt,
|
||
|
|
redirectUri: code.redirectUri,
|
||
|
|
scope: code.scope || '',
|
||
|
|
client: { id: client.id },
|
||
|
|
user: { uid: user.uid },
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
const blockName = this.fileName + "--" + "saveAuthorizationCode";
|
||
|
|
this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
async getAuthorizationCode(authorizationCode) {
|
||
|
|
try {
|
||
|
|
// 1. 从数据库中查询授权码信息
|
||
|
|
const { code, type } = JSON.parse(authorizationCode);
|
||
|
|
const lastCode = type[type.length - 1];
|
||
|
|
const redisDbType = this.redisType[lastCode];
|
||
|
|
let rdmcode;
|
||
|
|
if(type == 'code') {
|
||
|
|
rdmcode = await this.ctx.app.redis.get('db3').get(code);
|
||
|
|
} else {
|
||
|
|
rdmcode = await this.ctx.app.redis.get(redisDbType).get(code);
|
||
|
|
}
|
||
|
|
if (!rdmcode) return false;
|
||
|
|
|
||
|
|
// 2. 从数据库中查询客户端信息、用户信息
|
||
|
|
const cloneRdmcode = JSON.parse(rdmcode);
|
||
|
|
const cloneLastCode = cloneRdmcode.uid[cloneRdmcode.uid.length-1];
|
||
|
|
const modelDbType = this.modelType[cloneLastCode];
|
||
|
|
const user = await modelDbType.findOne({ where: { uid: cloneRdmcode.uid } });
|
||
|
|
if (!user) return false;
|
||
|
|
|
||
|
|
// 3. 返回数据
|
||
|
|
return {
|
||
|
|
code: authorizationCode,
|
||
|
|
expiresAt: new Date(cloneRdmcode.expiresAt),
|
||
|
|
redirectUri: cloneRdmcode.redirectUri,
|
||
|
|
scope: cloneRdmcode.scope,
|
||
|
|
client: { id: cloneRdmcode.clientId },
|
||
|
|
user: { uid: cloneRdmcode.uid },
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
const blockName = this.fileName + "--" + "getAuthorizationCode";
|
||
|
|
this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
async revokeAuthorizationCode(authorizationCode) {
|
||
|
|
try {
|
||
|
|
// 从数据库中查询该授权码并删除
|
||
|
|
const { code, type } = JSON.parse(authorizationCode.code);
|
||
|
|
const lastCode = type[type.length - 1];
|
||
|
|
const redisDbType = this.redisType[lastCode];
|
||
|
|
let revokeValue;
|
||
|
|
if(type == 'code') {
|
||
|
|
revokeValue = await this.ctx.app.redis.get('db3').del(code);
|
||
|
|
} else {
|
||
|
|
revokeValue = await this.ctx.app.redis.get(redisDbType).del(code);
|
||
|
|
}
|
||
|
|
if(revokeValue){
|
||
|
|
return true;
|
||
|
|
}else{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
const blockName = this.fileName + "--" + "revokeAuthorizationCode";
|
||
|
|
this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
async getRefreshToken(refreshToken) {
|
||
|
|
try {
|
||
|
|
// 1. 查询数据库获取刷新令牌
|
||
|
|
const rdmrefresh = await this.ctx.app.redis.get(refreshToken);
|
||
|
|
if (!rdmrefresh) return false;
|
||
|
|
|
||
|
|
// 2. 返回数据
|
||
|
|
return {
|
||
|
|
refreshToken: JSON.parse(rdmrefresh).token,
|
||
|
|
refreshTokenExpiresAt: new Date(JSON.parse(rdmrefresh).expiresAt),
|
||
|
|
scope: JSON.parse(rdmrefresh).scope,
|
||
|
|
client: { id: JSON.parse(rdmrefresh).clientId },
|
||
|
|
user: { uid: JSON.parse(rdmrefresh).uid },
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
const blockName = this.fileName + "--" + "getRefreshToken";
|
||
|
|
this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return Model;
|
||
|
|
};
|