NodeJS 自定义授权lambda函数节点js [已关闭]

w8f9ii69  于 2023-02-08  发布在  Node.js
关注(0)|答案(1)|浏览(119)

昨天关门了。
Improve this question
如何在AWS中使用node js通过https API为lambda函数使用自定义授权器
我是这个领域的新手,所以我没有这方面的经验。任何帮助都非常感谢。

gcxthw6b

gcxthw6b1#

在各自的文件名下创建以下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

中间件-授权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/*'],
          },
      },
  };
};

授权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);
  }
};

相关问题