JavaScript và Cookie

Bài viết này giải thích về JavaScript và cookie.

Chúng tôi sẽ giải thích cẩn thận từng bước một, từ kiến thức cơ bản về cookie, cách đọc và ghi, bảo mật cho đến các ví dụ thực tế.

YouTube Video

javascript-cookie.html
  1<!DOCTYPE html>
  2<html lang="en">
  3<head>
  4  <meta charset="UTF-8">
  5  <title>JavaScript &amp; HTML</title>
  6  <style>
  7    * {
  8        box-sizing: border-box;
  9    }
 10
 11    body {
 12        margin: 0;
 13        padding: 1em;
 14        padding-bottom: 10em;
 15        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 16        background-color: #f7f9fc;
 17        color: #333;
 18        line-height: 1.6;
 19    }
 20
 21    .container {
 22        max-width: 800px;
 23        margin: 0 auto;
 24        padding: 1em;
 25        background-color: #ffffff;
 26        border: 1px solid #ccc;
 27        border-radius: 10px;
 28        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
 29    }
 30
 31    .container-flex {
 32        display: flex;
 33        flex-wrap: wrap;
 34        gap: 2em;
 35        max-width: 1000px;
 36        margin: 0 auto;
 37        padding: 1em;
 38        background-color: #ffffff;
 39        border: 1px solid #ccc;
 40        border-radius: 10px;
 41        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
 42    }
 43
 44    .left-column, .right-column {
 45        flex: 1 1 200px;
 46        min-width: 200px;
 47    }
 48
 49    h1, h2 {
 50        font-size: 1.2rem;
 51        color: #007bff;
 52        margin-top: 0.5em;
 53        margin-bottom: 0.5em;
 54        border-left: 5px solid #007bff;
 55        padding-left: 0.6em;
 56        background-color: #e9f2ff;
 57    }
 58
 59    button {
 60        display: block;
 61        margin: 1em auto;
 62        padding: 0.75em 1.5em;
 63        font-size: 1rem;
 64        background-color: #007bff;
 65        color: white;
 66        border: none;
 67        border-radius: 6px;
 68        cursor: pointer;
 69        transition: background-color 0.3s ease;
 70    }
 71
 72    button:hover {
 73        background-color: #0056b3;
 74    }
 75
 76    #output {
 77        margin-top: 1em;
 78        background-color: #1e1e1e;
 79        color: #0f0;
 80        padding: 1em;
 81        border-radius: 8px;
 82        min-height: 200px;
 83        font-family: Consolas, monospace;
 84        font-size: 0.95rem;
 85        overflow-y: auto;
 86        white-space: pre-wrap;
 87    }
 88
 89    .highlight {
 90        outline: 3px solid #ffc107; /* yellow border */
 91        background-color: #fff8e1;  /* soft yellow background */
 92        transition: background-color 0.3s ease, outline 0.3s ease;
 93    }
 94
 95    .active {
 96        background-color: #28a745; /* green background */
 97        color: #fff;
 98        box-shadow: 0 0 10px rgba(40, 167, 69, 0.5);
 99        transition: background-color 0.3s ease, box-shadow 0.3s ease;
100    }
101  </style>
102</head>
103<body>
104    <div class="container">
105        <h1>JavaScript Console</h1>
106        <button id="executeBtn">Execute</button>
107        <div id="output"></div>
108    </div>
109
110    <script>
111        // Override console.log to display messages in the #output element
112        (function () {
113            // Override console.log
114            const originalLog = console.log;
115            console.log = function (...args) {
116                originalLog.apply(console, args);
117                const message = document.createElement('div');
118                message.textContent = args.map(String).join(' ');
119                output.appendChild(message);
120            };
121
122            // Override console.error
123            const originalError = console.error;
124            console.error = function (...args) {
125                originalError.apply(console, args);
126                const message = document.createElement('div');
127                message.textContent = args.map(String).join(' ');
128                message.style.color = 'red'; // Color error messages red
129                output.appendChild(message);
130            };
131        })();
132
133        document.getElementById('executeBtn').addEventListener('click', () => {
134            // Prevent multiple loads
135            if (document.getElementById('externalScript')) return;
136
137            const script = document.createElement('script');
138            script.src = 'javascript-cookie.js';
139            script.id = 'externalScript';
140            //script.onload = () => console.log('javascript-cookie.js loaded and executed.');
141            //script.onerror = () => console.log('Failed to load javascript-cookie.js.');
142            document.body.appendChild(script);
143        });
144    </script>
145</body>
146</html>

JavaScript và Cookie

Cookienhững phần dữ liệu nhỏ được lưu trữ trong trình duyệt của người dùng. Chúng chủ yếu được sử dụng cho các mục đích sau:.

  • Xác thực người dùng (duy trì trạng thái đăng nhập)
  • Lưu cài đặt người dùng (ngôn ngữ, giao diện, v.v.)
  • Theo dõi (lịch sử duyệt web, v.v.)

Trong JavaScript, bạn có thể đọc và ghi cookie bằng cách sử dụng document.cookie.

Tạo (ghi) cookie

Cookie được tạo với cú pháp sau:.

1document.cookie = "username=JohnDoe";
  • Đoạn mã này lưu một cookie có tên là "username=JohnDoe" vào trình duyệt.

Tạo cookie có ngày hết hạn

Cookie có thể được thiết lập ngày hết hạn. Nếu không thiết lập ngày hết hạn, cookie đó sẽ được coi là cookie phiên và sẽ bị xóa khi trình duyệt đóng lại.

1const date = new Date();
2date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7 days
3const cookieText = "username=JohnDoe; expires=" + date.toUTCString() + "; path=/; SameSite=None; Secure"
4document.cookie = cookieText;
5console.log(`Cookie Text  : ${cookieText}`);
6console.log(`Cookie Value : ${document.cookie}`);
  • Thuộc tính expires xác định ngày hết hạn của cookie theo định dạng UTC.
  • Thuộc tính path xác định đường dẫn mà cookie sẽ được gửi. / nghĩa là toàn bộ trang web.
  • Nếu bạn chỉ định SameSite=None, Cookie sẽ được gửi ngay cả với các yêu cầu từ trang web khác. Tuy nhiên, trong trường hợp này, bạn luôn phải thêm thuộc tính Secure.
  • Việc chỉ định Secure giới hạn Cookie chỉ được gửi qua kết nối HTTPS, tăng cường bảo mật.
  • Bằng cách truy xuất document.cookie, bạn có thể lấy tất cả các Cookie đang có trên trang hiện tại dưới dạng chuỗi.
  • Bằng cách sử dụng console.log, bạn có thể kiểm tra sự khác biệt giữa giá trị thực tế của Cookie được thiết lập trong trình duyệt và giá trị có thể truy xuất được.

Lấy (đọc) cookie

Bạn có thể lấy tất cả cookie dưới dạng chuỗi bằng document.cookie.

1const date = new Date();
2date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7 days
3document.cookie = "theme=dark; expires=" + date.toUTCString() + "; path=/; SameSite=None; Secure"
4
5console.log(document.cookie);
6// Output: "username=JohnDoe; theme=dark"
  • Giá trị trả về của document.cookie là một chuỗi duy nhất trong đó tất cả các Cookie được nối lại theo định dạng 'key=value;'.
  • Sử dụng một hàm để phân tích chuỗi này và trích xuất giá trị mong muốn rất tiện lợi.

Hàm lấy giá trị của một cookie

 1function getCookie(name) {
 2    const cookies = document.cookie.split('; ');
 3    for (const cookie of cookies) {
 4        const [key, value] = cookie.split('=');
 5        if (key === name) {
 6            return decodeURIComponent(value);
 7        }
 8    }
 9    return null;
10}
11
12console.log(getCookie("username")); // "JohnDoe"
  • Hàm này tách các khóa và giá trị bằng cách sử dụng split() và trả về giá trị nếu khóa đó trùng khớp với khóa được chỉ định.
  • Bằng cách sử dụng decodeURIComponent, bạn có thể lấy lại chính xác các ký tự đã được mã hóa.
  • Nếu khóa tương ứng không tồn tại, hàm sẽ trả về null.

Xóa cookie

Một cookie có thể bị xóa bằng cách thiết lập ngày hết hạn của nó là một ngày trong quá khứ.

1document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=None; Secure";
2
3console.log(document.cookie);
4// Output: "theme=dark"
  • Bằng cách gán giá trị rỗng cho username và đặt ngày hết hạn trong quá khứ, cookie sẽ bị xóa.
  • Khi xóa một Cookie, bạn cũng cần chỉ định giống thuộc tính path, SameSiteSecure như khi tạo.
  • Trong ví dụ này, username đã bị xóa nhưng các Cookie khác như theme=dark vẫn còn.

Tùy chọn cho cookie

Bạn có thể chỉ định các tùy chọn khác nhau để kiểm soát hành vi của một cookie. Các tùy chọn chính bao gồm:.

Chỉ định ngày hết hạn của cookie theo định dạng UTC. Nếu không chỉ định, cookie sẽ trở thành cookie phiên và bị xóa khi trình duyệt đóng lại.

Chỉ định thời gian tồn tại của cookie tính bằng giây. Tùy chọn này sẽ ưu tiên hơn `expires`.

Chỉ định đường dẫn mà cookie sẽ được gửi kèm. Ví dụ, nếu bạn chỉ định `/admin`, cookie sẽ chỉ được gửi đến các trang dưới đường dẫn đó.

Chỉ định miền mà cookie có hiệu lực. Thông thường, nó được thiết lập cho miền hiện tại, nhưng bạn cũng có thể áp dụng cho tất cả các tên miền phụ, như `.example.com`.

Khi thuộc tính này được chỉ định, cookie chỉ được gửi qua HTTPS. Để tăng cường bảo mật, nên luôn thiết lập thuộc tính này cho thông tin nhạy cảm.

Kiểm soát việc cookie có được gửi khi có yêu cầu từ các trang web khác hay không. Bạn có thể chỉ định một trong ba giá trị sau:.

- `Strict`
    Cookie chỉ được gửi cho các yêu cầu từ cùng một trang web.

- `Lax`
    Cookie được gửi khi điều hướng bình thường, nhưng có một số giới hạn.

- `None`
    Cookie có thể được gửi ngay cả khi yêu cầu đến từ trang web khác. Tuy nhiên, thuộc tính `Secure` cũng được yêu cầu.

Ví dụ: Cookie bảo mật

1document.cookie = "sessionId=abc123; secure; SameSite=Strict";
  • Nếu bạn chỉ định secure, Cookie sẽ chỉ được gửi qua giao thức HTTPS.
  • Nếu chỉ định SameSite=Strict, Cookie sẽ không được gửi cho các yêu cầu từ trang web khác, hữu hiệu như một biện pháp chống CSRF.
  • Những thuộc tính bảo mật như vậy là cần thiết cho các Cookie quan trọng, dùng cho xác thực hoặc quản lý phiên.

Mã hóa và giải mã

Vì giá trị của cookie có thể chứa các ký tự đặc biệt, việc sử dụng encodeURIComponent sẽ an toàn hơn.

1const date = new Date();
2date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7 days
3
4const username = "JohnDoe";
5document.cookie =
6    "username=" + encodeURIComponent(username) +
7    "; max-age=604800; path=/; SameSite=None; Secure";
8
9console.log(decodeURIComponent(getCookie("username"))); // "JohnDoe"
  • Bằng cách sử dụng encodeURIComponent, bạn có thể lưu an toàn các khoảng trắng, ký hiệu, v.v. vào Cookie.
  • Khi đọc giá trị, hãy dùng decodeURIComponent để trả về chuỗi gốc.
  • Trong ví dụ này, max-age=604800 được sử dụng để đặt thời hạn hết hạn là 7 ngày (604.800 giây). Đây là cách chỉ định ngày hết hạn, tương tự như thuộc tính expires. max-age có thể được chỉ định bằng giây và thường dễ sử dụng hơn.

Ví dụ thực tế: Lưu và tải giao diện

Dưới đây là ví dụ về việc lưu giao diện mà người dùng đã chọn vào cookie và tự động áp dụng nó khi truy cập lần sau.

 1function setTheme(theme) {
 2    document.cookie =
 3        "theme=" + encodeURIComponent(theme) +
 4        "; max-age=604800; path=/; SameSite=None; Secure"; // 1 week
 5    applyTheme(theme);
 6}
 7
 8function applyTheme(theme) {
 9    document.body.style.backgroundColor = theme === "dark" ? "#333" : "#fff";
10    document.body.style.color = theme === "dark" ? "#fff" : "#000";
11}
12
13function getCookie(name) {
14    const cookies = document.cookie.split('; ');
15    for (const cookie of cookies) {
16        const [key, value] = cookie.split('=');
17        if (key === name) {
18            return decodeURIComponent(value);
19        }
20    }
21    return null;
22}
23
24const savedTheme = getCookie("theme");
25if (savedTheme) {
26    applyTheme(savedTheme);
27}
1<button onclick="setTheme('light')">Light</button>
2<button onclick="setTheme('dark')">Dark</button>
  • Hàm setTheme lưu chủ đề bạn chọn vào Cookie và ngay lập tức gọi applyTheme để cập nhật giao diện.
  • Hàm applyTheme sẽ thay đổi màu nền và màu chữ của body tùy theo chủ đề đã chọn.
  • Ví dụ này, do đã thiết lập max-age=604800, cài đặt chủ đề sẽ được giữ lại trong một tuần.
  • Vì lựa chọn của người dùng có thể được giữ lại khi truy cập lại trang, UX được cải thiện.

Giới hạn và lưu ý về cookie

Hãy chú ý các điểm sau khi sử dụng cookie:.

  • Giới hạn kích thước Kích thước của một cookie bị giới hạn khoảng 4KB.

  • Giới hạn số lượng cookie có thể lưu trữ Tùy vào trình duyệt, bạn chỉ có thể lưu khoảng 20 đến 50 cookie trên mỗi tên miền.

  • Lưu ý về bảo mật Nội dung của Cookie về cơ bản được lưu dưới dạng văn bản thuần túy, do đó không phù hợp để lưu trữ thông tin mật như mật khẩu.

  • Cookies không thể truy cập từ JavaScript Các Cookie có thuộc tính HttpOnly không thể đọc được từ JavaScript vì lý do bảo mật.

Máy chủ và Cookie

1Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict

Một số thuộc tính của Cookie, chẳng hạn như HttpOnly, không thể thiết lập qua JavaScript. Các thuộc tính này phải được thiết lập ở phía máy chủ.

Tóm tắt

Việc thao tác với Cookie bằng JavaScript có thể nâng cao trải nghiệm người dùng và giữ được trạng thái. Tuy nhiên, hãy lưu ý những điểm sau để xử lý chúng một cách an toàn và phù hợp.

  • Chỉ lưu trữ những thông tin cần thiết tối thiểu Theo quan điểm bảo mật và quyền riêng tư, tránh lưu trữ thông tin cá nhân hoặc nhạy cảm, chỉ lưu dữ liệu cần thiết.

  • Thiết lập đúng các thuộc tính bảo mật Thiết lập các thuộc tính như SecureSameSite để ngăn các cuộc tấn công chéo trang như XSS và CSRF.

  • Mã hóa và Giải mã Dữ liệu Sử dụng encodeURIComponentdecodeURIComponent để lưu trữ và đọc giá trị Cookie một cách an toàn để các ký tự đặc biệt và tiếng Nhật có thể được xử lý chính xác.

Bằng cách học cách sử dụng đúng Cookie, bạn có thể xây dựng các ứng dụng web tiên tiến và an toàn hơn.

Bạn có thể làm theo bài viết trên bằng cách sử dụng Visual Studio Code trên kênh YouTube của chúng tôi. Vui lòng ghé thăm kênh YouTube.

YouTube Video