Hướng dẫn bảo mật api nodejs
Chào các bạn, sau đây mình xin giới thiệu cho các bạn loạt bài viết về việc Sử dụng TypeScript để viết API bảo mật với Node.js và Express. Trong khuôn khổ 5 bài có thể sẽ không đầy đủ và sai sót nhiều. Mong các bạn comment góp ý. Mình xin cảm ơn. Show Tổng quan các bài viết
Mình sẽ ra lần lượt các bài. Trong bài viết đầu tiên Giới thiệu và cài đặt ban đầu, mình sẽ hướng dẫn cách cài đặt TypeScript trong Node.js và Framework Express sử dụng Hot-Module Replacement của webpack. Tôi sẽ lấy một ví dụ cụ thể về việc làm một trang web mà liên quan đến menu của nhà hàng. Qua đó sẽ tìm hiểu cách xây dựng API đầy đủ tính năng bằng Node.js, Express và TypeScript, cho phép client thực hiện các thao tác với data trên các resources (ở đây là menu của nhà hàng). Sử dụng TypeScript với Node.js cho phép bạn truy cập vào việc kiểm tra kiểu tĩnh tùy chọn cùng với công cụ mạnh mẽ cho các ứng dụng lớn và các tính năng ECMAScript mới nhất. Ngoài ra, chúng ta sẽ tìm hiểu cách xác định data models, tạo data service và xây dựng các modular endpoints. Chúng ta cũng có thể sử dụng Auth0 để bảo mật API. Chúng ta sẽ sử dụng rule trong business để hạn chế quyền truy cập API:
Để đơn giản, tôi sẽ lưu data ngay trong RAM. Nội dung
Các bạn tạo thư mục mới tùy ý để chứa project. Mình đặt tên là 1 2 3 mkdir typescript-secure-api cd typescript-secure-api
Tiếp theo, khởi tạo một project Node.js mới với file 1 2 npm init -y 2. Cài đặt các dependeccy Chúng ta cần require một số các dependency để tạo server Express bảo mật với TypeScript. 1 2 npm i express dotenv cors helmet
Cài đặt typescript như các dependency 1 2 npm i -D typescript
Để sử dụng TypeScript hiệu quả, cần cài đặt định nghĩa kiểu cho các packages trên 1 2 npm i -D @types/node @types/express @types/dotenv @types/cors @types/helmet
Khi một package không có các loại build-in, bạn có thể cài đặt định nghĩa kiểu thông qua @types npm namespace – nơi lưu trữ các định nghĩa kiểu của TypeScript trong project DefiniteTyped. Khi các package được cài đặt, các types sẽ tự động được compiler của TypeScript include vào. 3. Khởi tạo TypeScript với Node.jsĐể giúp compiler của TypeScript hiểu cấu trúc project, cần tạo file 1 2 npx tsc --init
Đó là tất cả những gì bạn cần để định configure project này với các giá trị mặc định. 4. Sử dụng biến môi trường envThay vì sử dụng các hard-coded configuration variables trong các file, bạn có thể xác định tất cả các biến đó ở một file và import chúng vào các module nếu cần. File này thương có tên là 1 2 touch .env
Trong file, mình định nghĩa PORT của server: 1 2 PORT=7000
Bằng cách sử dụng package dotenv, trong bất cứ module nào mình cũng có thể sử dụng biến local được định nghĩa trong file .env Chú ý : Trong file .env có thể chứa các thông tin nhạy cảm VD như API keys,… Vì vậy nên thêm file này vào .gitignore.5. Tạo Node App với Express sử dụng TypeScript Để cho project có cấu trúc tốt, mình sẽ thêm một folder 1 2 mkdir src
Trong folder 1 2 touch src/endtrypoint.ts
Dưới đây sẽ là nội dung của file 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /** * Required External Modules */
/** * App Variables */
/** * App Configuration */
/** * Server Activation */
/** * Webpack HMR Activation */
Tại mỗi phần comment, mình sẽ thêm nội dung như sau: 1 2 3 4 5 6 7 8 9 10 11 /** * Required External Modules */
import * as dotenv from "dotenv"; import express from "express"; import cors from "cors"; import helmet from "helmet";
dotenv.config();
Phần 1 2 3 4 5 6 7 8 9 10 11 12 /** * App Variables */
if (!process.env.PORT) { process.exit(1); }
const PORT: number = parseInt(process.env.PORT as string, 10);
const app = express();
Phần 1 2 3 4 5 6 7 8 /** * App Configuration */
app.use(helmet()); app.use(cors()); app.use(express.json());
Chúng ta cho phép các CORS request bằng method 1 2 3 4 5 6 7 8 /** * Server Activation */
const server = app.listen(PORT, () => { console.log(`Listening on port ${PORT}`); }); 6. Set Up Hot-Module Replacement (HMR) for TypeScript with Webpack Quá trình compile TypeScript có thể làm tăng thời gian khởi động. Tuy nhiên, nếu có bất cứ thay đổi nào trong sourcecode, bạn không cần recompile toàn bộ project. Chúng ta có thể thiết lập webpack Hot-Module Replacement (HMR) để giảm đáng kể thời gian khởi động lại khi thực hiện thay đổi. Cài đặt Webpack Dependencies cho TypeScript1 2 npm i -D ts-loader webpack webpack-cli webpack-node-externals
Trong thư mục project tạo file 1 2 touch webpack.config.ts
Với nội dung dưới đây 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 const webpack = require("webpack"); const path = require("path"); const nodeExternals = require("webpack-node-externals");
module.exports = { entry: ["webpack/hot/poll?100", "./src/endtrypoint.ts"], watch: true, target: "node", externals: [ nodeExternals({ whitelist: ["webpack/hot/poll?100"] }) ], module: { rules: [ { test: /.tsx?$/, use: "ts-loader", exclude: /node_modules/ } ] }, mode: "development", resolve: { extensions: [".tsx", ".ts", ".js"] }, plugins: [new webpack.HotModuleReplacementPlugin()], output: { path: path.join(__dirname, "dist"), filename: "endtrypoint.js" } };
Có nhiều điều cần nói trong file config webpack này, nhưng tôi chỉ đề cập đến những task ở high-level cần hiểu:
Enable Hot-Module Replacement trong ứng dụng ExpressĐể Enable Hot-Module Replacement (HMR) trong Express server, cần update lại file 1 2 3 4 5 6 7 8 9 /** * Webpack HMR Activation */
if (module.hot) { module.hot.accept(); module.hot.dispose(() => server.close()); }
Bình tĩnh, hãy đọc tiếp phần dưới khi thấy lỗi báo đỏ Ở đây, chúng ta nhận thấy rằng Hot-Module Replacement đã enable thông qua HotModuleReplocationPlugin cho module được xác định trong Sử dụng interface method accept() để accept các module và các dependency của nó cập nhật. Sau đó, interface method dispose() được thực hiện khi module cuối cùng được thay thế. Các hành động xóa hay thoát sẽ xóa mọi resources đã tạo, VD kết thúc ứng dụng Node.js và thoát tất cả các kết nối hiện có. Do
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 /** * Webpack HMR Activation */
type ModuleId = string | number;
interface WebpackHotModule { hot?: { data: any; accept( dependencies: string[], callback?: (updatedDependencies: ModuleId[]) => void, ): void; accept(dependency: string, callback?: () => void): void; accept(errHandler?: (err: Error) => void): void; dispose(callback: (data: any) => void): void; }; }
declare const module: WebpackHotModule;
if (module.hot) { module.hot.accept(); module.hot.dispose(() => server.close()); }
Run server Node-Express và TypeScriptVới việc cài đặt HMR, cần cài đặt thêm 2 script trong file 1 2 3 4 5 6 "main": "endtrypoint.js", "scripts": { "start": "node dist/endtrypoint", "webpack": "webpack --config webpack.config.ts" },
Để chạy, chúng ta sẽ mở 2 cửa sổ terminal, một cái để gọi tới 1 2 npm run webpack
Một cái để gọi tới 1 2 npm start
Trong terminal chạy Như vậy, mình đã xong phần một hướng dẫn Giới thiệu và cài đặt ban đầu cho loạt seri về việc Sử dụng TypeScript để viết API bảo mật với Node.js và Express. |