【发布时间】:2023-02-06 00:59:33
【问题描述】:
如何使用节点 js 通过 AWS 中的 https API 为 lambda 函数使用自定义授权方
我是该领域的新手,所以我没有这方面的经验。非常感谢任何帮助。
【问题讨论】:
-
Stackoverflow 是一个针对您可能遇到的特定问题提出特定问题的地方。请阅读此页面:stackoverflow.com/help/how-to-ask
标签: node.js amazon-s3 aws-lambda jwt
如何使用节点 js 通过 AWS 中的 https API 为 lambda 函数使用自定义授权方
我是该领域的新手,所以我没有这方面的经验。非常感谢任何帮助。
【问题讨论】:
标签: node.js amazon-s3 aws-lambda jwt
在各自的文件名下创建以下 3 个文件(serverless.yml、middleware-auth.js、auth.js),并在这些文件中写入代码。这允许对 AWS lambda 函数进行自定义授权。
无服务器.yml
provider:
name: aws
runtime: nodejs14.x
lambdaHashingVersion: 20201221
# you can overwrite defaults here
stage: dev
region: us-east-1
apiGateway:
binaryMediaTypes:
- "*/*"
httpApi:
cors: true
authorizers:
customAuthorizer:
type: request
functionName: authoriserAnyToken
functions:
authoriserAnyToken:
handler: middleware-auth.handler
signin:
handler: auth.signin
timeout: 15
events:
- httpApi:
path: /auth/{role}/signin
method: post
auth_remember_me:
handler: auth.auth_remember_me
timeout: 15
events:
- httpApi:
path: /auth/remember-me
method: post
authorizer:
name: customAuthorizer
type: request
auth_jwt_token_check:
handler: auth.auth_jwt_token_check
timeout: 15
events:
- httpApi:
path: /auth/jwt/check
method: post
authorizer:
name: customAuthorizer
type: request
中间件-auth.js
const JWT_SECRET = "goK!pusp6ThEdURUtRenOwUhAsSURESHBazl!uJLPlS8EbreWLdrupIwabRAsiBa";
const jwt = require("jsonwebtoken");
exports.handler = async event => {
console.log('event', event);
const token = event.headers.authorization? event.headers.authorization.replace('Bearer ', ''): null;
if (!token) {
console.log('could not find a token on the event');
return generatePolicy({ allow: false });
}
try {
const decoded = jwt.verify(token, JWT_SECRET);
console.log('token_details ', decoded);
if(decoded.user == 'admin'){
return generatePolicy({ allow: true });
}
else if (decoded.user == 'seller')
{
return generatePolicySeller({ allow: true });
}
} catch (error) {
console.log('error ', error);
return generatePolicy({ allow: false });
}
};
const generatePolicy = ({ allow }) => {
return {
principalId: 'token',
policyDocument: {
Version: '2012-10-17',
Statement: {
Action: 'execute-api:Invoke',
Effect: allow ? 'Allow' : 'Deny',
Resource: '*',
// Resource: 'arn:aws:execute-api:us-east-1:*:*/*/*',
// Resource: 'arn:aws:execute-api:us-east-1:*:*/*/auth/*',
},
},
};
};
const generatePolicySeller = ({ allow }) => {
return {
principalId: 'token',
policyDocument: {
Version: '2012-10-17',
Statement: {
Action: 'execute-api:Invoke',
Effect: allow ? 'Allow' : 'Deny',
// Resource: '*',
// Resource: 'arn:aws:execute-api:us-east-1:*:*/*/*',
Resource: ['arn:aws:execute-api:us-east-1:*:*/*/sellers/*','arn:aws:execute-api:us-east-1:*:*/*/auth/*'],
},
},
};
};
auth.js
'use strict';
const jsonwebtoken = require("jsonwebtoken");
const bcrypt = require('bcrypt');
const AWS = require("aws-sdk");
const s3 = new AWS.S3()
const MAX_SIZE = 2097152 // 2MB
const bucket = 'S3_BUCKET_NAME' // Name of your bucket.
const Busboy = require("busboy")
const JWT_SECRET = "goK!pusp6ThEdURUtRenOwUhAsSURESHBazl!uJLPlS8EbreWLdrupIwabRAsiBa";
// Tables
const USERS_TABLE = 'users'
const { Validator } = require('node-input-validator');
s3.config.update({
region: "us-east-1",
accessKeyId: 'S3_ACCESS_KEY_ID', // ACCESS_KEY_ID of your S3 bucket.
secretAccessKey: 'S3_SECRET_ACCESS_KEY' // SECRET_ACCESS_KEY of your S3 bucket.
});
const mysql = require('serverless-mysql')({ // DB configuration
config: {
host: process.env.DB_HOST,
port: process.env.DB_PORT,
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
debug: false
}
});
const sendJSON = (code, message, data) => {
let resData = {
"status": code < 400 ? 'Success' : 'Error',
"message": message,
}
data ? (resData["data"] = data) : null;
return {
statusCode: code,
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
...resData
})
};
}
const FORM = {
parse(body, headers) {
return new Promise((resolve, reject) => {
const data = {};
const buffer = Buffer.from(body, 'base64');
const bb = Busboy({
headers: Object.keys(headers).reduce((newHeaders, key) => {
// busboy expects lower-case headers.
newHeaders[key.toLowerCase()] = headers[key];
return newHeaders;
}, {})
});
bb.on('field', (name, val, info) => {
data[name] = val;
});
bb.on('error', (err) => {
reject(err);
});
bb.on('close', () => {
resolve(data);
});
bb.end(buffer);
});
}
};
module.exports.signin = async (event, context) => {
try {
const data = await FORM.parse(event['body'], event['headers']);
const v = new Validator(data, {
email: 'required|email',
password: 'required'
});
const matched = await v.check();
if (!matched)
return {
statusCode: 400,
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(v.errors),
};
let results = "";
let email = data.email;
let password = data.password;
const role = event.pathParameters.role;
results = await mysql.query(`SELECT * FROM ${USERS_TABLE} WHERE email = ? LIMIT 1`, [email]);
await mysql.end();
if (!results[0]) {
return {
statusCode: 400,
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
email: {
"message": "User not found"
}
}),
};
} else {
let user_hash = results[0].password;
user_hash = user_hash.replace(/^$2y(.+)$/i, '$2a$1');
const match = await bcrypt.compare(password, user_hash);
if (!match) {
return {
statusCode: 400,
body: JSON.stringify({
password: {
"message": "Missing or Invalid password"
}
}),
};
}
const user_info = {
'id' : results[0].id,
'role': results[0].role,
'fname' : results[0].fname,
'lname' : results[0].lname
};
const token = jsonwebtoken.sign({ id: results[0].id, user: results[0].role, fname: results[0].fname, lname: results[0].lname}, JWT_SECRET, { expiresIn: "2h" });
return sendJSON(200, 'Successfully logged.',{
'user' : user_info,
'token': token
});
}
} catch (e) {
return sendJSON(400, e.message);
}
};
module.exports.auth_jwt_token_check = async (event) => {
try {
return sendJSON(200, 'verifyed user');
} catch (e) {
return sendJSON(400, e.message);
}
};
module.exports.auth_remember_me = async (event) => {
try {
const token = event.headers.authorization? event.headers.authorization.replace('Bearer ', ''): null;
const decoded = jsonwebtoken.verify(token, JWT_SECRET);
const new_token = jsonwebtoken.sign({ id: decoded.id, user: decoded.user, fname: decoded.fname, lname: decoded.lname}, JWT_SECRET, { expiresIn: "2h" });
return sendJSON(200, 'Get Renew Token.', {
'token': new_token
});
} catch (e) {
return sendJSON(400, e.message);
}
};
【讨论】: