簡體   English   中英

使用 JS 服務器時間而不是客戶端時間來避免這種行為,即用戶可以通過更改本地機器時鍾來操縱結果

[英]Using JS server time instead of client time to avoid this behavior where users can manipulate results by changing their local machine clock

預期行為

在每次刷新時向用戶顯示來自arr數組的隨機值(顏色)。 每天應將不同的文件( file-1.jsonfile-2.json等)加載到arr中。 這應該在 00:00 UTC 服務器時間重置。 僅應顯示當天相關文件中的值。

意外行為

一切正常,直到用戶更改本地機器/手機上的時鍾。 然后他們也可以有效地看到未來和過去的價值。 日期/時間可以在客戶端進行操作,這是不應該發生的。 每個人都應該得到服務器的時間,不管那是什么。

例子

  • :如果您在 2020 年 4 月 18 日訪問/刷新該站點,您應該會從file-1.json中選擇隨機顏色。

  • :如果您在 2020-04-19 訪問/刷新該網站,您應該會從file-2.json中選擇隨機顏色。

  • 不好:另一方面,如果您在 2020-04-18 將本地時鍾更改為 2020-04-19,則您應該無法從 2020-04-19 獲得隨機顏色,因為該日期在未來. 您仍然應該從今天的文件中獲得一個值,因為它仍然是 2020-04-18 服務器時間。

script.js

// Store today's date
const today = new Date();
var arr = [];
// Define milliseconds per day
const msPerDay = 1000*60*60*24;

// Uncomment line below to test future date by using the getDateByOffset() function
//const today = getDateByOffset(1);

// Get difference (in days) between two dates
function getDiffInDays(date1, date2){
    // `|0` is same as Math.floor(...)
    return ((date2.getTime() - date1.getTime())/msPerDay)|0;
}
// Get date by offset in days (Useful for testing tomorrow's date and so on)
function getDateByOffset(days=0){
    const today = new Date();
    return new Date((today.getTime()/msPerDay + days)*msPerDay);
}

// Get offset index for the json file
function getIndex(){
    // Define the starting date for "file-1.json"
    const startDate = new Date(Date.parse('4/18/2020'));
    // Will range from 1 instead of 0
    return getDiffInDays(startDate, today) + 1;
}
new Promise(resolve=>{
    // Get the json file based on the offset
    $.getJSON(`file-${getIndex()}.json`, resolve);
})
.then(json=>{
    // Add it to the `arr` array
    arr = [...arr,...json];
})
.then(()=>{
    console.log(arr);
    $("#show").text(arr[Math.floor(Math.random() * arr.length)]);
})

Netlify 上的演示

如何復制問題

只需將本地機器或手機的時鍾更改為 2020-04-19。 然后你會得到明天的 colors。

編輯:為了 100% 清楚,無論用戶如何使用他的本地設備設置(更改時鍾、IP 地址等)——他都不應該影響網站時間。

EDIT2:創建此端點以檢索日期和時間: https://bluexpress.netlify.app/.netlify/functions/server/getdate但我不確定它是否是正確的解決方案或如何將其正確集成到站點中。 協助表示贊賞!

那么答案很簡單:不要在客戶端計算文件名,而是將其設為單個 URI,根據日期動態計算服務器上的 JSON。

只要客戶端可以通過更改URI請求任何JSON數據,稍微精明的用戶即使不更改時鍾也可以訪問過去和未來的日子。 作為一般規則,不要信任客戶端,始終確保檢查服務器上的內容。

話雖如此,您也可以保留客戶端邏輯,但讓服務器根據日期拒絕(例如 404 左右)訪問“錯誤日期”的文件。 但是你必須有服務器邏輯來排除客戶端濫用。

答案可以根據

  1. 如果使用服務器端腳本呈現 HTML
  2. 如果您有一個服務器端點來檢索服務器的日期和時間

您可以執行其中任何一項並將服務器的時間作為變量獲取 javascript 的可見 scope

然后使用該變量將文件名確定為file-1 file-2

要使用 Node.JS 服務器端代碼,請遵循Netlify:Punch Setup

您可以使用世界時間 API/api/ip功能根據用戶的公共 ip 地址獲取 api。 就像是

// Modify the getIndex function to receive today's date instead
function getIndex(today){
    const startDate = new Date(Date.parse('4/15/2020'));
    const offset = getDiffInDays(startDate, today) + 1;
    return offset;
}   
// Get date from server
function getServerDate(){
    // Unfortunately, we need to bypass Cross-Origin Request (CORs)
    return fetch(`https://cors-anywhere.herokuapp.com/http://worldtimeapi.org/api/ip`)
    // Convert response to json
    .then(res=>res.json())
    // Get the datetime from object and create a Date object
    .then(({datetime})=>new Date(Date.parse(datetime)))
    // Get json index based on the date
    .then(getIndex);
}

使用上面的 function 你可以簡單

// Get today's date from server
getServerDate()
.then(index=>new Promise(resolve=>{
    // Get the json file based on the index returned
    $.getJSON(`data-${index}.json`, resolve);
}))
.then(json=>{
    // Append to arr and whatever you like here
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM