Trong bài trước, chúng ta đã cùng tìm hiểu về các kiến thức cơ bản và cơ chế hoạt động của JWT. Trong bài này, anh em mình sẽ tiếp tục cùng nhau tìm hiểu về một phần mà mình nghĩ là hay nhất khi đề cập đến JWT, đó là áp dụng Mã hóa đối xứng và Mã hóa bất đối xứng trong xác thực JWT.
Mình sẽ sử dụng NodeJS và MongoDB để triển khai việc mã hóa cho JWT. Còn về ý tưởng, cách thức áp dụng thì anh em dùng ngôn ngữ lập trình nào cũng chơi được hết nhé.
Xác thực JWT cùng Mã hóa đối xứng và Mã hóa bất đối xứng
1. Xác thực JWT cùng Mã hóa đối xứng
Mã hóa đối xứng là phương thức mã hóa dữ liệu sử dụng cùng một key vừa để mã hóa và vừa để giải mã thông tin.
Cách làm này chắc không còn xa lạ gì với anh em khi ban đầu tiếp xúc với JWT.
Cách triển khai cơ bản như sau:
Đối với cách triển khai này, chúng ta tạo một JWT với một payload chứa thông tin về userid và email.
- Chúng ta sử dụng phương thức jwt.sign() để mã hóa thông tin này với key secretKey và thời gian sống của token là 1 giờ.
- Sau đó, chúng ta sử dụng phương thức jwt.verify() để xác thực JWT với key secretKey và lấy thông tin.
Anh em tham khảo source code GIT ở đây nhé.
B1: Import thư viện và khởi tạo secretKey
1 2 3 4 5 | <span class="token comment">// jwt.aes.js</span> <span class="token comment">// Import thư viện và khởi tạo secretKey</span> <span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'jsonwebtoken'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> secretKey <span class="token operator">=</span> <span class="token string">'mysupersecretkey'</span><span class="token punctuation">;</span> |
B2: Tạo hàm tạo JWT
1 2 3 4 5 6 | <span class="token comment">// Hàm tạo JWT</span> <span class="token keyword">const</span> <span class="token function-variable function">genToken</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">userInfo</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> accessToken <span class="token operator">=</span> jwt<span class="token punctuation">.</span><span class="token function">sign</span><span class="token punctuation">(</span><span class="token punctuation">{</span> userid<span class="token operator">:</span> userInfo<span class="token punctuation">.</span>_id<span class="token punctuation">,</span> email<span class="token operator">:</span> userInfo<span class="token punctuation">.</span>email <span class="token punctuation">}</span><span class="token punctuation">,</span> secretKey<span class="token punctuation">,</span> <span class="token punctuation">{</span> expiresIn<span class="token operator">:</span> <span class="token string">'1h'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> accessToken<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
B3: Tạo hàm xác thực JWT
1 2 3 4 5 6 7 8 9 10 11 | <span class="token comment">// Hàm xác thực JWT</span> <span class="token keyword">const</span> <span class="token function-variable function">validateToken</span> <span class="token operator">=</span> <span class="token keyword">async</span><span class="token punctuation">(</span><span class="token parameter">accessToken</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> jwt<span class="token punctuation">.</span><span class="token function">verify</span><span class="token punctuation">(</span>accessToken<span class="token punctuation">,</span> secretKey<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> decode</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">'error verify token'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span><span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'decode jwt::'</span><span class="token punctuation">,</span> decode<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
B4: Kiểm tra kết quả
1 2 3 4 5 6 7 8 | <span class="token comment">// Thực thi</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">runScript</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> userId <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token keyword">const</span> accessToken <span class="token operator">=</span> <span class="token function">genToken</span><span class="token punctuation">(</span><span class="token punctuation">{</span>_id<span class="token operator">:</span> userId<span class="token punctuation">,</span> email<span class="token operator">:</span> <span class="token string">'pdthien@gmail.com'</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">await</span> <span class="token function">validateToken</span><span class="token punctuation">(</span>accessToken<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">runScript</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
- Ưu điểm:
- Dễ thực hiện vì sử dụng 1 key duy nhất để vừa mã hóa và giải mã thông tin.
- Giảm áp lực cho phía server vì không phải lưu thêm dữ liệu gì cho việc xác thực.
- Nhược điểm: Không an toàn vì khi hacker ăn cắp được key đó, sẽ dễ dàng tạo ra các fake JWT, có thể truy cập tấn công ứng dụng.
2. Xác thực JWT cùng Mã hóa bất đối xứng
Mã hóa bất đối xứng sử dụng 2 key khác nhau (public key và private key) để mã hóa và giải mã thông tin. Trong đó, public key được chia sẻ với mọi người và private key được giữ bí mật.
- Private key được sử dụng để mã hóa (sign) thông tin tạo ra JWT.
- Public key được sử dụng để giải mã (verify) JWT đó, không có chiều ngược lại. Nên dù hacker có lấy được Public key cũng không thể tạo được fake JWT truy cập được ứng dụng.
Cách thức triển khai như sau:
Đối với cách triển khai này, chúng ta tạo một JWT với một payload chứa thông tin về userid và email
- Chúng ta sử dụng MongoDB để tạo bảng KeyToken lưu userId và publicKey.
- Tạo 2 key privateKey và publicKey sử dụng thuật toán rsa thông qua thư viện crypto.
- Chúng ta sử dụng phương thức jwt.sign() để mã hóa thông tin này với key privateKey và thời gian sống của token là 1 giờ.
- Chúng ta sử dụng phương thức jwt.verify() để xác thực JWT với key publicKey và lấy thông tin.
Anh em tham khảo source code GIT ở đây nhé.
B1: Khởi tạo kết nối MongoDB
1 2 3 4 5 6 7 8 9 10 | <span class="token comment">// init.mongodb.js</span> <span class="token keyword">const</span> mongoose <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"mongoose"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> connnectString <span class="token operator">=</span> <span class="token string">'mongodb://127.0.0.1:27017/jwt-auth'</span><span class="token punctuation">;</span> mongoose<span class="token punctuation">.</span><span class="token function">connect</span><span class="token punctuation">(</span>connnectString<span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">_</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'mongoDB connected'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">err</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'mongDB error '</span> <span class="token operator">+</span> err<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> module<span class="token punctuation">.</span>exports <span class="token operator">=</span> mongoose<span class="token punctuation">;</span> |
B2: Tạo bảng (collection) Key lưu trữ Public key
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span class="token comment">// keytoken.model.js</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> Schema<span class="token punctuation">,</span> model <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mongoose'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">DOCUMENT_NAME</span> <span class="token operator">=</span> <span class="token string">'Key'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">COLLECTION_NAME</span> <span class="token operator">=</span> <span class="token string">'Keys'</span><span class="token punctuation">;</span> <span class="token keyword">var</span> keyTokenSchema <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Schema</span><span class="token punctuation">(</span><span class="token punctuation">{</span> userid<span class="token operator">:</span> <span class="token punctuation">{</span> type<span class="token operator">:</span> Number<span class="token punctuation">,</span> required<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> publicKey<span class="token operator">:</span> <span class="token punctuation">{</span> type<span class="token operator">:</span> String<span class="token punctuation">,</span> require<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> timestamps<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> collection<span class="token operator">:</span> <span class="token constant">COLLECTION_NAME</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token function">model</span><span class="token punctuation">(</span><span class="token constant">DOCUMENT_NAME</span><span class="token punctuation">,</span> keyTokenSchema<span class="token punctuation">)</span><span class="token punctuation">;</span> |
B3: Tạo hàm genToken. Trong hàm xử lý 2 việc: Lưu public key vào DB + Dùng privateKey để mã hóa tạo JWT
1 2 3 4 5 6 7 | <span class="token comment">// jwt.rsa.js</span> <span class="token comment">// Import thư viện và các biến</span> <span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'jsonwebtoken'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> crypto <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'crypto'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./init.mongodb'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> keytokenModel <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./keytoken.model.js"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
1 2 3 4 5 6 7 8 9 | <span class="token comment">// Hàm xử lý lưu public key vào DB</span> <span class="token keyword">const</span> <span class="token function-variable function">createKeyToken</span> <span class="token operator">=</span> <span class="token keyword">async</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>userid<span class="token punctuation">,</span> publicKey<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> publicKeyString <span class="token operator">=</span> publicKey<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> filter <span class="token operator">=</span> <span class="token punctuation">{</span>userid<span class="token operator">:</span> userid<span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> update <span class="token operator">=</span> <span class="token punctuation">{</span>userid<span class="token operator">:</span> userid<span class="token punctuation">,</span> publicKey<span class="token operator">:</span> publicKeyString<span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> options <span class="token operator">=</span> <span class="token punctuation">{</span>upsert<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token keyword">new</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">await</span> keytokenModel<span class="token punctuation">.</span><span class="token function">findOneAndUpdate</span><span class="token punctuation">(</span>filter<span class="token punctuation">,</span> update<span class="token punctuation">,</span> options<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 | <span class="token comment">// Hàm tạo JWT từ private key</span> <span class="token keyword">const</span> <span class="token function-variable function">createAccessToken</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token parameter">payload<span class="token punctuation">,</span> privateKey</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> accessToken <span class="token operator">=</span> <span class="token keyword">await</span> jwt<span class="token punctuation">.</span><span class="token function">sign</span><span class="token punctuation">(</span>payload<span class="token punctuation">,</span> privateKey<span class="token punctuation">,</span> <span class="token punctuation">{</span> algorithm<span class="token operator">:</span> <span class="token string">'RS256'</span><span class="token punctuation">,</span> expiresIn<span class="token operator">:</span> <span class="token string">'1h'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> accessToken<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token comment">// Hàm genToken. Xử lý 2 việc: Lưu public key vào DB + Dùng private key để mã hóa tạo JWT.</span> <span class="token keyword">const</span> <span class="token function-variable function">genToken</span> <span class="token operator">=</span> <span class="token keyword">async</span><span class="token punctuation">(</span><span class="token parameter">userInfo</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// Dùng rsa để tạo privateKey và publicKey</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> privateKey<span class="token punctuation">,</span> publicKey <span class="token punctuation">}</span> <span class="token operator">=</span> crypto<span class="token punctuation">.</span><span class="token function">generateKeyPairSync</span><span class="token punctuation">(</span><span class="token string">'rsa'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> modulusLength<span class="token operator">:</span> <span class="token number">4096</span><span class="token punctuation">,</span> publicKeyEncoding<span class="token operator">:</span> <span class="token punctuation">{</span> type<span class="token operator">:</span> <span class="token string">'pkcs1'</span><span class="token punctuation">,</span> format<span class="token operator">:</span> <span class="token string">'pem'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> privateKeyEncoding<span class="token operator">:</span> <span class="token punctuation">{</span> type<span class="token operator">:</span> <span class="token string">'pkcs1'</span><span class="token punctuation">,</span> format<span class="token operator">:</span> <span class="token string">'pem'</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// Lưu userid và publicKey vào bảng KeyToken</span> <span class="token keyword">await</span> <span class="token function">createKeyToken</span><span class="token punctuation">(</span><span class="token punctuation">{</span> userid<span class="token operator">:</span> userInfo<span class="token punctuation">.</span>_id<span class="token punctuation">,</span> publicKey <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// Tạo accessToken với privateKey</span> <span class="token keyword">const</span> accessToken <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">createAccessToken</span><span class="token punctuation">(</span><span class="token punctuation">{</span> userid<span class="token operator">:</span> userInfo<span class="token punctuation">.</span>_id<span class="token punctuation">,</span> email<span class="token operator">:</span> userInfo<span class="token punctuation">.</span>email <span class="token punctuation">}</span><span class="token punctuation">,</span> privateKey<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> accessToken<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
B4: Tạo hàm validateToken xử lý xác thực JWT: Lấy publicKey từ DB + Xác thực (verify) token từ publicKey.
1 2 3 4 5 6 7 | <span class="token comment">// Hàm lấy publicKey</span> <span class="token keyword">const</span> <span class="token function-variable function">getPublicKey</span> <span class="token operator">=</span> <span class="token keyword">async</span><span class="token punctuation">(</span><span class="token parameter">userid</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> filter <span class="token operator">=</span> <span class="token punctuation">{</span>userid<span class="token operator">:</span> userid<span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> token <span class="token operator">=</span> <span class="token keyword">await</span> keytokenModel<span class="token punctuation">.</span><span class="token function">findOne</span><span class="token punctuation">(</span>filter<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> token<span class="token punctuation">.</span>publicKey<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token comment">// Hàm validateToken. Xử lý 2 việc: Lấy publicKey từ DB + Xác thực (verify) token từ publicKey</span> <span class="token keyword">const</span> <span class="token function-variable function">validateToken</span> <span class="token operator">=</span> <span class="token keyword">async</span><span class="token punctuation">(</span><span class="token parameter">accessToken<span class="token punctuation">,</span> userID</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// Lấy publicKey trong DB</span> <span class="token keyword">const</span> publicKeyString <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">getPublicKey</span><span class="token punctuation">(</span>userID<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Convert publicKey từ dạng string về dạng rsa có thể đọc được</span> <span class="token keyword">const</span> publicKeyObject <span class="token operator">=</span> crypto<span class="token punctuation">.</span><span class="token function">createPublicKey</span><span class="token punctuation">(</span>publicKeyString<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// xác thực accessToken sử dụng publicKey</span> jwt<span class="token punctuation">.</span><span class="token function">verify</span><span class="token punctuation">(</span>accessToken<span class="token punctuation">,</span> publicKeyObject<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> decode</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">'error verify token'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span><span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'decode jwt::'</span><span class="token punctuation">,</span> decode<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
B5: Kiểm tra kết quả
1 2 3 4 5 6 7 | <span class="token comment">// Thực thi</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">runScript</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> userId <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token keyword">let</span> accessToken <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">genToken</span><span class="token punctuation">(</span><span class="token punctuation">{</span>_id<span class="token operator">:</span> userId<span class="token punctuation">,</span> email<span class="token operator">:</span> <span class="token string">'pdthien@gmail.com'</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">await</span> <span class="token function">validateToken</span><span class="token punctuation">(</span>accessToken<span class="token punctuation">,</span> userId<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
- Nhược điểm: Phải lưu thêm Public key vào DB và truy xuất tới DB để lấy Public key khi cần xác thực, dẫn tới hiệu năng có thể bị ảnh hưởng. Tuy nhiên, ta hoàn toàn có thể cải thiện hiệu năng bằng cách sử dụng Cache như MemoryCache hoặc RedisCache.
- Ưu điểm:
- Tuy làm gia tăng áp lực cho server khi phải lưu thêm Public key vào DB và lấy ra sử dụng khi cần xác thực, nhưng nó giúp cho hệ thống của chúng ta gia tăng bảo mật hơn rất nhiều.(Vì như mình đã nói ở trên, dù hacker có đọc được thông tin Public key từ DB, cũng không thể tạo được fake JWT để truy cập ứng dụng do Private key chỉ được dùng để mã hóa (sign) thông tin tạo JWT, còn Public key chỉ được dùng để giải mã JWT để lấy thông tin, không có chiều ngược lại)
- Giải quyết được một số nhược điểm của JWT như phần 1 mình đã chỉ ra cho anh em:
- Về vấn đề về Rủi ro bảo mật, thì khi áp dụng phương pháp mã hóa bất đối xứng, ta hoàn toàn có thể yên tâm vì độ bảo mật đã được nâng cao hơn rất nhiều (mình đã giải thích ở trên).
- Đối với vấn đề Không thể hủy bỏ token và Không hỗ trợ quản lý phiên, thì khi áp dụng phương pháp này, do chúng đã ta lưu publicKey trong DB, nên để hủy bỏ token hay hủy phiên đăng nhập của người dùng một cách đơn giản, ta chỉ việc xóa publicKey đó khỏi DB.
Anh em tham khảo source code GIT ở đây nhé.
Kết
Tổng kết lại một chút, khi anh em áp dụng mã hoá đối xứng vào JWT thì sẽ dễ thực hiện hơn và server không cần phải lưu thêm thông tin gì cho việc xác thực, qua đó làm tăng hiệu năng, tuy nhiên lại giảm bảo mật vì hacker chỉ cần lấy được sercetKey là có thể fake JWT để truy cập hệ thống. Còn khi áp dụng mã hoá bất đối xứng, ta cần phải lưu thêm publicKey vào DB, tuy có thể làm giảm hiệu năng một chút nhưng bù lại nó giúp ta gia tăng bảo mật hơn rất nhiều.
Nếu anh em có góp ý hay thảo luận thì comment ngay dưới bài viết nhé. Tks all !!!