jwt - Cách chúng tôi bảo mật với sự giúp đỡ của redis

Nội dung bài viết

jsonwebtoken rất dễ bị tấn công vì nhiều yếu tố trong đó việc lưu trữ access token trên Client cũng là một trong điểm yếu đó. Có hai cách phổ biến để tránh bị đánh cắp đó là đừng sử dụng jwt hoặc không để token ở máy khách. Chúng tôi đã chọn cách không lưu trên Client. Và chúng tôi làm thế nào?

Xem thêm: Những ý tưởng thực hiện với jsonwebtoken

Ý tưởng về kỹ thuật

Thật ra ý tưởng này rất hay, nó xuất phát từ việc tránh lưu trữ token ở máy khách. Vậy không lưu trữ ở máy khách, thì token lưu ở đâu, và Client lấy token đâu để isAuthenticated(). Thật ra, có lưu đấy nhưng không phải lưu token mà lưu một keyword để đại diện mà thôi.

Ví dụ: Thay vì bạn nhìn thấy một token dưới cookie như thế này:

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiQW5vbnlzdGljayIsImVtYWlsIjoiQW5vbnlzdGlja0BtYWlsLmNvbSIsInBhc3N3b3JkIjoicGFzczEyMzQiLCJpYXQiOjE2MjQ5MzU2ODAsImV4cCI6MTYyNTAyMjA4MH0.H7FxVIsZQLXrKDbfawBr8ngI-ZcOneHEhTzfT1iKBco"

Thì bạn sẽ nhìn thấy nó như sau:

abc-id-xyz: 1

Đây, vậy thì bố ai mà đánh cắp và sửa được. Một ý tưởng bảo mật hay mà bạn có thể sử dụng linh hoạt, thêm thắt vào ứng dụng của bạn.

Secure token

Trên đó là lý thuyết, vậy cách triển khai như thế nào? Xem code dưới đây:

Hình ảnh

Đầu tiên tôi sẽ set một key cho redis:

127.0.0.1:6379> set tokenCouter 0
OK
127.0.0.1:6379>

Sau đó nếu User login thành công thì sẽ gán tokenCouter cho giá trị token.

const fakeUser = {
    name: "Anonystick",
    email: "Anonystick@mail.com",
    password: "pass1234"
};
client.get("tokenCouter", (err, data) => {
     // Lấy giá trị hiện tại của tokenCouter
    client.set("tokenCouter", parseInt(data) + 1);
    //Tạo token thành công, sau đó thiết lập lại
    jwt.sign(fakeUser, "secret", { expiresIn: "1d" }, (err, token) => {
        client.set(parseInt(data) + 1, token);
        res.cookie("jwt-id", parseInt(data) + 1); //set cookie cho Client
    });
});

Sau đó chúng ta sẽ xem lại dưới redis thế nào:

127.0.0.1:6379> get tokenCouter
"1"
127.0.0.1:6379> get 1
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiQW5vbnlzdGljayIsImVtYWlsIjoiQW5vbnlzdGlja0BtYWlsLmNvbSIsInBhc3N3b3JkIjoicGFzczEyMzQiLCJpYXQiOjE2MjQ5MzU2ODAsImV4cCI6MTYyNTAyMjA4MH0.H7FxVIsZQLXrKDbfawBr8ngI-ZcOneHEhTzfT1iKBco"
127.0.0.1:6379>

Rất chi là ok.

Và bây giờ chúng ta check lại:

const { id } = req.body;
// Lây giá trị hiện tại mà redis đang lưu trữ.
client.get(id, (err, data) => {
    jwt.verify(data, "secret", async (err, payload) => {
        console.log(payload);
    });
});

So ez. Xem thêm những bài viết liên quan đến jsonwebtoken.

Có thể bạn đã bị missing