You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止许可校验代码受系统日期篡改影响?

Hey there! Let's tackle this license expiration check problem you're facing—totally get why modifying the system date breaks your current code, since it relies entirely on the user's untrusted local clock. As someone new to this space, here are some practical, actionable approaches to fix this, ordered from simple to more robust:

1. Use a Trusted Server-Side Timestamp (Most Reliable)

The core issue with your current code is that it trusts the user's local system clock, which is easy to manipulate. Instead, fetch the real current time from your own backend server every time you need to validate the license. The server's clock is under your control, so users can't tamper with it.

Here's a simplified example using JavaScript's fetch API:

// Request the current timestamp from your backend endpoint
fetch('/api/get-valid-timestamp')
  .then(response => response.json())
  .then(data => {
    // Parse the server's trusted timestamp
    const serverCurrentDate = new Date(data.timestamp);
    // Use ISO date format for consistent parsing across all browsers
    const licenseExpiryDate = new Date('2021-12-31');

    if (licenseExpiryDate > serverCurrentDate) {
      // License is valid—proceed with your app logic
    } else {
      alert("Your licence has expired!");
    }
  })
  .catch(error => {
    // Handle cases where the server request fails (e.g., no internet)
    alert("Could not verify license status. Please check your internet connection.");
  });

Your backend just needs to return a UTC timestamp or ISO 8601 date string (like 2024-05-20T12:00:00Z). This approach eliminates local date tampering entirely, though it requires an internet connection.

2. Add Offline Support with Local Timestamp Safeguards

If your app needs to work offline, you can combine server timestamps with local storage to track elapsed time without trusting the user's clock:

function getTrustedDate() {
  const lastServerTimestamp = localStorage.getItem('lastValidServerTime');
  const currentLocalTime = new Date().getTime();

  if (!lastServerTimestamp) {
    // First run or no stored data—must fetch from server
    return fetch('/api/get-valid-timestamp')
      .then(res => res.json())
      .then(data => {
        const serverTime = new Date(data.timestamp).getTime();
        localStorage.setItem('lastValidServerTime', serverTime);
        return new Date(serverTime);
      });
  } else {
    const storedServerTime = parseInt(lastServerTimestamp);
    const timeElapsedSinceLastCheck = currentLocalTime - storedServerTime;

    if (timeElapsedSinceLastCheck >= 0) {
      // User hasn't rolled back the clock—calculate trusted time
      const trustedTime = new Date(storedServerTime + timeElapsedSinceLastCheck);
      
      // Refresh the server timestamp every 24 hours to keep it accurate
      const oneDayMs = 24 * 60 * 60 * 1000;
      if (timeElapsedSinceLastCheck > oneDayMs) {
        fetch('/api/get-valid-timestamp')
          .then(res => res.json())
          .then(data => {
            localStorage.setItem('lastValidServerTime', new Date(data.timestamp).getTime());
          });
      }
      return Promise.resolve(trustedTime);
    } else {
      // User rolled back the clock—force a server refresh
      return fetch('/api/get-valid-timestamp')
        .then(res => res.json())
        .then(data => {
          const serverTime = new Date(data.timestamp).getTime();
          localStorage.setItem('lastValidServerTime', serverTime);
          return new Date(serverTime);
        });
    }
  }
}

// Use the trusted date for license check
getTrustedDate().then(trustedDate => {
  const licenseExpiryDate = new Date('2021-12-31');
  if (licenseExpiryDate > trustedDate) {
    // Valid license logic
  } else {
    alert("Your licence has expired!");
  }
});

This method uses the user's local clock only to track time passed since the last server check—if they roll back the date, we detect the negative elapsed time and re-fetch the real server time.

3. Move Critical Logic to the Backend (For High-Value Licenses)

If your license protects paid or sensitive features, client-side checks alone are never 100% secure—users can easily edit your JavaScript code (via browser dev tools, for example) to bypass the check.

For these cases:

  • Host core functionality on your backend API
  • Every request to use premium features first validates the license status against your server's clock
  • Only return valid responses if the license is active

This way, even if users tamper with client code, they can't access the features without passing the server's validation.

Quick Fix for Your Original Code

One small note: new Date('31/12/2021') can cause parsing errors in some browsers (date formats vary by locale). Use the ISO format instead: new Date('2021-12-31') for consistent results.

内容的提问来源于stack exchange,提问作者milevicm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 18:47:30