阿里云主机折上折
  • 微信号
Current Site:Index > Cookie operation

Cookie operation

Author:Chuan Chen 阅读数:45675人阅读 分类: JavaScript

What are Cookies

Cookies are small pieces of text data stored on a user's local device, sent from the server to the browser and saved locally. They are primarily used to record user status, store user preferences, or track user behavior. Cookies typically consist of key-value pairs, with each cookie also containing attributes such as domain, path, and expiration time.

// A typical cookie example
document.cookie = "username=JohnDoe; expires=Thu, 18 Dec 2025 12:00:00 UTC; path=/";

Basic Cookie Operations

Setting Cookies

In JavaScript, cookies can be set by directly assigning values to document.cookie. When setting a cookie, you need to specify the name and value, and you can also add other optional attributes.

// Set a simple cookie
document.cookie = "theme=dark";

// Set a cookie with an expiration time
const date = new Date();
date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); // Expires in 7 days
document.cookie = `user_token=abc123; expires=${date.toUTCString()}`;

// Set a cookie with a path
document.cookie = "preferences=font_large; path=/settings";

Reading Cookies

To read all cookies, you can use the document.cookie property, which returns a string of all cookies for the current domain in the format "name=value; name2=value2".

// Get all cookies
const allCookies = document.cookie;
console.log(allCookies); // "theme=dark; user_token=abc123; preferences=font_large"

// Function to get a specific cookie
function getCookie(name) {
  const cookies = document.cookie.split('; ');
  for (const cookie of cookies) {
    const [cookieName, cookieValue] = cookie.split('=');
    if (cookieName === name) {
      return decodeURIComponent(cookieValue);
    }
  }
  return null;
}

const theme = getCookie('theme'); // "dark"

Deleting Cookies

Deleting a cookie is actually done by setting an expired cookie.

// Delete a cookie
document.cookie = "theme=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";

// Generic function to delete a cookie
function deleteCookie(name, path = '/') {
  document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path};`;
}

deleteCookie('user_token');

Detailed Explanation of Cookie Attributes

Expiration Time (expires/max-age)

Controls the lifespan of a cookie, which can be a specific date (expires) or a number of seconds (max-age).

// Set expiration time using expires
const expiresDate = new Date();
expiresDate.setDate(expiresDate.getDate() + 30);
document.cookie = `promo_shown=1; expires=${expiresDate.toUTCString()}`;

// Set expiration time using max-age (in seconds)
document.cookie = "session_id=xyz789; max-age=3600"; // Expires in 1 hour

Path

Specifies the URL path prefix where the cookie is available. The default is the current path.

// Cookie only available under the /admin path
document.cookie = "admin_token=secret; path=/admin";

// Cookie available site-wide
document.cookie = "language=en; path=/";

Domain

Specifies the domain where the cookie is available. The default is the current domain.

// Cookie available on the main domain and all subdomains
document.cookie = "shared_id=123; domain=.example.com";

// Cookie only available on a specific subdomain
document.cookie = "subdomain_data=abc; domain=shop.example.com";

Secure Flag

Cookies marked as Secure can only be transmitted over HTTPS.

// Secure cookie
document.cookie = "auth_token=secure123; Secure";

HttpOnly Flag

Prevents JavaScript access and can only be set by the server via HTTP response headers.

Set-Cookie: session=abc123; HttpOnly

Cookie Limitations

Browsers impose certain limitations on cookies:

  1. Limited number of cookies per domain (usually around 50)
  2. Size limit per cookie (usually 4KB)
  3. Total cookie size limit (varies by browser)
// Function to test cookie size limits
function testCookieSizeLimit() {
  let size = 0;
  const cookieName = 'size_test';
  
  try {
    while (true) {
      size += 100;
      const value = 'a'.repeat(size);
      document.cookie = `${cookieName}=${value}`;
      if (!document.cookie.includes(cookieName)) break;
    }
  } catch (e) {
    console.error(e);
  } finally {
    document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC`;
  }
  
  return size - 100;
}

const maxSize = testCookieSizeLimit();
console.log(`Max cookie size: ${maxSize} characters`);

Practical Examples

User Preference Settings

// Save user theme preference
function saveThemePreference(theme) {
  const expires = new Date();
  expires.setFullYear(expires.getFullYear() + 1);
  document.cookie = `user_theme=${theme}; expires=${expires.toUTCString()}; path=/`;
}

// Load saved theme
function loadThemePreference() {
  const theme = getCookie('user_theme');
  if (theme) {
    document.documentElement.setAttribute('data-theme', theme);
  }
}

// Toggle theme
function toggleTheme() {
  const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
  const newTheme = currentTheme === 'light' ? 'dark' : 'light';
  document.documentElement.setAttribute('data-theme', newTheme);
  saveThemePreference(newTheme);
}

Shopping Cart Functionality

// Add to cart
function addToCart(productId, quantity = 1) {
  const cart = getCart();
  cart[productId] = (cart[productId] || 0) + quantity;
  saveCart(cart);
}

// Remove from cart
function removeFromCart(productId) {
  const cart = getCart();
  delete cart[productId];
  saveCart(cart);
}

// Get cart contents
function getCart() {
  const cartCookie = getCookie('shopping_cart');
  return cartCookie ? JSON.parse(cartCookie) : {};
}

// Save cart
function saveCart(cart) {
  const expires = new Date();
  expires.setDate(expires.getDate() + 7);
  document.cookie = `shopping_cart=${JSON.stringify(cart)}; expires=${expires.toUTCString()}; path=/`;
}

Security Considerations for Cookies

Cross-Site Scripting (XSS)

Since cookies can be accessed by JavaScript, they are vulnerable to XSS attacks.

// Malicious script could steal cookies
const stolenCookies = document.cookie;
// Send to attacker's server...

Prevention measures:

  1. Use HttpOnly flag
  2. Encode cookie values
  3. Implement Content Security Policy (CSP)

Cross-Site Request Forgery (CSRF)

Attackers may use a user's cookies to make malicious requests.

Prevention measures:

  1. Use SameSite attribute
  2. Add CSRF tokens
// Set SameSite attribute
document.cookie = "session_id=abc123; SameSite=Lax";

// Or stricter SameSite=Strict
document.cookie = "sensitive_data=xyz; SameSite=Strict; Secure";

Sensitive Data Storage

Avoid storing sensitive information in cookies, such as passwords or credit card numbers.

// Unsafe practice
document.cookie = `password=${userPassword}`;

// Better practice is to store a session ID
document.cookie = `session_id=${generateSecureToken()}; Secure; HttpOnly; SameSite=Strict`;

Cookie Alternatives

While cookies have many uses, there may be better alternatives in certain scenarios:

Web Storage API

// localStorage - persistent storage
localStorage.setItem('user_settings', JSON.stringify(settings));
const settings = JSON.parse(localStorage.getItem('user_settings'));

// sessionStorage - session-level storage
sessionStorage.setItem('temp_data', 'value');
const tempData = sessionStorage.getItem('temp_data');

IndexedDB

Suitable for storing large amounts of structured data.

// Open or create a database
const request = indexedDB.open('myDatabase', 1);

request.onupgradeneeded = (event) => {
  const db = event.target.result;
  const store = db.createObjectStore('products', { keyPath: 'id' });
};

request.onsuccess = (event) => {
  const db = event.target.result;
  const transaction = db.transaction('products', 'readwrite');
  const store = transaction.objectStore('products');
  
  // Add data
  store.add({ id: 1, name: 'Product 1', price: 9.99 });
  
  // Retrieve data
  const getRequest = store.get(1);
  getRequest.onsuccess = () => {
    console.log(getRequest.result);
  };
};

Modern Cookie Management

Batch Cookie Operations

When handling multiple cookies, utility functions can be created:

class CookieManager {
  static set(name, value, options = {}) {
    let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
    
    if (options.expires instanceof Date) {
      cookie += `; expires=${options.expires.toUTCString()}`;
    }
    
    if (options.maxAge) {
      cookie += `; max-age=${options.maxAge}`;
    }
    
    if (options.path) {
      cookie += `; path=${options.path}`;
    }
    
    if (options.domain) {
      cookie += `; domain=${options.domain}`;
    }
    
    if (options.secure) {
      cookie += '; Secure';
    }
    
    if (options.sameSite) {
      cookie += `; SameSite=${options.sameSite}`;
    }
    
    document.cookie = cookie;
  }
  
  static get(name) {
    const cookies = document.cookie.split('; ');
    for (const cookie of cookies) {
      const [cookieName, cookieValue] = cookie.split('=');
      if (decodeURIComponent(cookieName) === name) {
        return decodeURIComponent(cookieValue);
      }
    }
    return null;
  }
  
  static delete(name, path = '/') {
    this.set(name, '', {
      expires: new Date(0),
      path
    });
  }
  
  static getAll() {
    const cookies = {};
    document.cookie.split('; ').forEach(cookie => {
      const [name, value] = cookie.split('=');
      cookies[decodeURIComponent(name)] = decodeURIComponent(value);
    });
    return cookies;
  }
}

// Usage example
CookieManager.set('user', 'john', { 
  maxAge: 3600, 
  path: '/', 
  sameSite: 'Lax' 
});

const user = CookieManager.get('user');
CookieManager.delete('user');

Cookie Integration with Frameworks

Using cookies in modern frameworks like React or Vue:

// React example - using a higher-order component to manage cookies
function withCookies(WrappedComponent) {
  return class extends React.Component {
    setCookie = (name, value, options) => {
      CookieManager.set(name, value, options);
    };
    
    getCookie = (name) => {
      return CookieManager.get(name);
    };
    
    deleteCookie = (name, path) => {
      CookieManager.delete(name, path);
    };
    
    render() {
      return (
        <WrappedComponent 
          {...this.props}
          setCookie={this.setCookie}
          getCookie={this.getCookie}
          deleteCookie={this.deleteCookie}
        />
      );
    }
  };
}

// Using the higher-order component
class UserPreferences extends React.Component {
  componentDidMount() {
    const theme = this.props.getCookie('theme') || 'light';
    this.setState({ theme });
  }
  
  handleThemeChange = (theme) => {
    this.props.setCookie('theme', theme, { maxAge: 365 * 24 * 3600 });
    this.setState({ theme });
  };
  
  render() {
    // ...
  }
}

export default withCookies(UserPreferences);

Cookie Performance Optimization

Large or numerous cookies can impact page performance, especially since they are sent with every HTTP request.

Reducing Cookie Size

  1. Use abbreviations or encoding to reduce cookie value size
  2. Only store necessary information
// Store minimal necessary data
const userData = {
  id: 123,
  // Instead of storing the entire user object
};

document.cookie = `user=${JSON.stringify(userData)}`;

Using CDN Domains to Separate Cookies

Serve static resources from cookie-free domains.

<!-- Main domain may set cookies -->
<img src="https://www.example.com/tracker.gif">

<!-- Static resources use cookie-free CDN -->
<img src="https://cdn.example.com/logo.png">

Regularly Clean Up Expired Cookies

// Function to clean up expired cookies
function cleanUpCookies() {
  const cookies = document.cookie.split('; ');
  const now = new Date();
  
  cookies.forEach(cookie => {
    const [name, ...parts] = cookie.split('=');
    const cookieStr = parts.join('=');
    
    // Check expiration time
    const expiresMatch = cookieStr.match(/expires=([^;]+)/i);
    if (expiresMatch) {
      const expiresDate = new Date(expiresMatch[1]);
      if (expiresDate < now) {
        document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;
      }
    }
  });
}

// Perform cleanup when the page loads
cleanUpCookies();

Cookie Debugging and Testing

Browser Developer Tools

Modern browsers provide tools to view and manipulate cookies:

  1. Chrome: Application > Storage > Cookies
  2. Firefox: Storage > Cookies
  3. Safari: Storage > Cookies

Unit Testing Cookie Operations

Use testing frameworks to test cookie-related code:

// Using Jest to test cookie operations
describe('CookieManager', () => {
  beforeEach(() => {
    // Clear all cookies before each test
    document.cookie.split('; ').forEach(cookie => {
      const [name] = cookie.split('=');
      document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC`;
    });
  });
  
  test('should set and get cookie', () => {
    CookieManager.set('test', 'value');
    expect(CookieManager.get('test')).toBe('value');
  });
  
  test('should delete cookie', () => {
    CookieManager.set('test', 'value');
    CookieManager.delete('test');
    expect(CookieManager.get('test')).toBeNull();
  });
  
  test('should handle special characters', () => {
    const value = '测试&value=123';
    CookieManager.set('special', value);
    expect(CookieManager.get('special')).toBe(value);
  });
});

Real-World Scenario Testing

Test cookie behavior in different environments:

  1. Different domains and subdomains
  2. HTTPS and HTTP
  3. Different paths
  4. Mobile and desktop devices
// Test cross-subdomain cookie sharing
function testCrossSubdomainCookie() {
  // Set cookie on main domain
  document.cookie = "cross_domain=test; domain=.example.com; path=/";
  
  // Check availability on subdomain
  fetch('https://sub.example.com/check-cookie')
    .then(response => response.json())
    .then(data => console.log('Cookie available on subdomain:', data.hasCookie));
}

Cookies and Privacy Regulations

With the implementation of privacy regulations like GDPR, cookie usage requires more caution.

Compliance Checks

  1. Provide clear explanations of cookie usage
  2. Obtain user consent (for non-essential cookies)
  3. Allow users to opt out
// Simple cookie consent banner implementation
class CookieConsent {
  constructor() {
    if (!this.getConsent()) {
      this.showBanner();
    }
  }
  
  showBanner() {
    const banner = document.createElement('div');
    banner.innerHTML = `
      <div class="cookie-banner">
        <p>We use cookies to enhance your experience. By continuing, you agree to our cookie policy.</p>
        <button id="accept-cookies">Accept</button>
        <button id="reject-cookies">Reject</button>
        <a href="/cookie-policy">Learn more</a>
      </div>
    `;
    document.body.appendChild(banner);
    
    document.getElementById('accept-cookies').addEventListener('click', () => {
      this.setConsent(true);
      banner.remove();
    });
    
    document.getElementById('reject-cookies').addEventListener('click', () => {
      this.setConsent(false);
      this.deleteNonEssentialCookies();
      banner.remove();
    });
  }
  
  setConsent(given) {
    localStorage.setItem('cookie_consent', given ? 'true' : 'false');
    if (given) {
      document.cookie = "cookie_consent=true; max-age=31536000; path=/";
    }
  }
  
  getConsent() {
    return localStorage.getItem('cookie_consent') === 'true' || 
           document.cookie.includes('cookie_consent=true');
  }
  
  deleteNonEssentialCookies() {
    // Delete all non-essential cookies
    const essentialCookies = ['session_id', 'csrf_token'];
    document.cookie.split('; ').forEach(cookie => {
      const [name] = cookie.split('=');
      if (!essentialCookies.includes(name)) {
        document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;
      }
    });
  }
}

// Initialize
new CookieConsent();

Privacy-Friendly Alternatives

  1. Use local storage instead of some cookies
  2. Reduce tracking cookie usage
  3. Provide anonymization options
// Anonymous user identification scheme
function getAnonymousUserId() {
  let userId = localStorage.getItem('anonymous_user_id');
  if (!userId) {
    userId = generateUUID(); // Generate random ID
    localStorage.setItem('anonymous_user_id', userId);

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.