Nội dung bài viết
Video học lập trình mỗi ngày
Ở bài viết trước, chúng ta đã làm rõ về cách lưu trữ token ở đâu trên Client. Và cách nào an toàn hơn và hạn chế được các XSS attack. Do đó ở bài này chúng ta sẽ triển khai xây dựng một RESTful APIs bảo mật token hạn chế việc đánh cắp khi mà càng ngày hackers luôn luôn rình mò ở quanh ta :D.
Để đọc và hiểu bài này thì những bạn chứ đọc bài trước "JSON Web Token: Lưu trữ và bảo mật tokens trên client như thế nào?" thì nên lướt qua để hiểu vì sao lại có bài viết này. Bắt đầu tạo cho mình một rest api thôi nào. Code full tôi sẽ post sau bài viết. Nhưng các bạn nên theo dõi từng bước trước để hiểu cách run một api thế nào rồi lúc đó download source về cũng chưa muộn nhé.
Code Full:
Phía Back-End: https://github.com/anonystick/demo-jwt-token
Phía Client: https://github.com/anonystick/demo-jwt-token-client
Trước tiên tôi tạo một file có tên là users.json. Chứa danh sách user hệ thống.
1 - Create users.json
[ { "id": 1, "name": "anonystick" }, { "id": 2, "name": "anonymous hackers" } ]
Nhiệm vụ của chúng ta khi truy cập vào http://localhost:3000/api/users thì chúng ta sẽ lấy được danh sách đó, tất nhiên là phải xác nhận được token.
2 - package.json
"name": "demo-auth-jwt", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "nodemon index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "nodemon": "^1.19.1" }, "dependencies": { "cookie-parser": "^1.4.4", "cors": "^2.8.5", "express": "^4.17.1", "jsonwebtoken": "^8.5.1" } }
Copy file này về rồi các bạn chỉ việc run command.
npm i
Cấu trúc một restful api đơn giản.
3 - index.js
//Khi user login xác nhận app.post('/auth/login', (req, res) => { try{ const email = req.body.email; const password = req.body.password; if(email !== 'anonystick@gmail.com' || password !== 'password'){ res.status(400); throw new Error('invalid infor') } const payload = { email: email } const token = jwt.sign(payload, SECRET); res.cookie('access_token', token, { maxAge: 365 * 24 * 60 * 60 * 100, httpOnly: true, //secure: true; }) res.status(200).json({ok: true}); }catch (err){ throw err } })
Nhiệm vụ app.post('/auth/login') là khi user xác nhận pass và email nếu thành công thì sẽ trả về cho user một token, đồng thời server sẽ set một cookie ở browser của client. Và cookie này ở user sẽ không bao giờ đọc được bởi javascript. Nó sẽ được browser tự động gửi đi khi có yêu cầu.
res.cookie('access_token', token, { maxAge: 365 * 24 * 60 * 60 * 100, // thời gian sống httpOnly: true, // chỉ có http mới đọc được token //secure: true; //ssl nếu có, nếu chạy localhost thì comment nó lại })
Nếu thành công thì các bạn có thể thấy như hình ảnh này.
Các bạn để ý các thuộc tính của một cookie nhé. Tiếp theo viết một service cho phép user request để lấy danh sách user.
app.use('/api/users', (req, res) => { const token = req.cookies.access_token; try{ const decoded = jwt.verify(token, SECRET); res.status(200).json(users); }catch(err){ res.status(400) throw err; } })
Chú ý:
const token = req.cookies.access_token
Khi user gọi http://localhost:3000/api/users thì mặc định browser sẽ gửi cookie đi theo nếu trên client cho phép.
const decoded = jwt.verify(token, SECRET);
Nếu verify thành công thì lúc đó client sẽ nhận được danh sách user. Quan trọng chúng ta install những package này vào webservice nhằm đảm bảo cho việc bảo vệ token.
app.use(express.json()) // for parsing application/json app.use(cookieParser()) //cookie-parser dùng để đọc cookies của request: app.use(cors({ origin: 'http://127.0.0.1:5500', //Chan tat ca cac domain khac ngoai domain nay credentials: true //Để bật cookie HTTP qua CORS }))
Code Full:
Phía Back-End: https://github.com/anonystick/demo-jwt-token
Phía Client: https://github.com/anonystick/demo-jwt-token-client