Использование JS времени сервера вместо времени клиента, чтобы избежать такого поведения, когда пользователи могут манипулировать результатами, изменяя часы своего локального компьютера - PullRequest
1 голос
/ 18 апреля 2020

Ожидаемое поведение

Показывать пользователям случайное значение (цвет) из массива arr при каждом refre sh. Каждый день в arr должен загружаться другой файл (file-1.json, file-2.json, et c). Это должно быть сброшено в 00:00 UT C по времени сервера. Должны отображаться только значения из файла, связанного с этим днем.

Неожиданное поведение

Все работает хорошо, пока пользователи не изменят часы на своих локальных машинах / телефонах. Тогда они могут также эффективно видеть будущие и прошлые ценности. Датой / временем можно манипулировать на стороне клиента, чего не должно быть. Каждый должен получить время сервера, что бы это ни было.

Примеры

  • Хорошо : если вы посещаете / refre sh сайт 2020-04-18, вы должны получить случайный цвет, выбранный из file-1.json.

  • Хорошо : если вы посещаете / refre sh сайт 2020-04-19, вы должны получить случайный цвет, выбранный из file-2.json.

  • Bad : с другой стороны, если в 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)]);
})

DEMO на Netlify

Как повторить проблему

Просто измените часы вашего локального компьютера или телефона на 2020-04-19. Тогда вы получите цвета завтрашнего дня.

РЕДАКТИРОВАТЬ: просто чтобы быть на 100% прозрачным, что бы пользователь ни делал со своими настройками локального устройства (изменение часов, IP-адреса и т. Д. c) - он должен НЕ может влиять на время веб-сайта.

EDIT2: создал эту конечную точку для получения даты и времени: https://bluexpress.netlify.app/.netlify/functions/server/getdate, но я не уверен, что это правильное решение или как правильно интегрировать его в сайт. Помощь приветствуется!

Ответы [ 3 ]

1 голос
/ 18 апреля 2020

ответ может быть дан на основе

  1. Если HTML отображается с использованием сценария на стороне сервера
  2. Если у вас есть конечная точка сервера для получения даты и времени на сервере

вы можете сделать любой из них и получить время сервера для видимой области видимости javascript в качестве переменной

Затем использовать эту переменную для определения имен файлов как file-1 file-2 et c

Чтобы использовать Node.JS серверный код, следуйте Netlify: Punch Setup

1 голос
/ 18 апреля 2020

Вы можете использовать API мирового времени /api/ip, чтобы получить API, основанный на IP-адресе пользователя publi c. Что-то вроде

// 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);
}

И используя вышеуказанную функцию, вы можете просто

// 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
})
1 голос
/ 18 апреля 2020

Тогда ответ прост: не вычисляйте имя файла на клиенте, а сделайте его единым URI, который динамически вычисляет JSON на сервере в зависимости от дня.

Пока клиент может запросить любую из данных JSON, изменив URI, пользователи, которые немного подкованы, могут получить доступ к прошлым и будущим дням, даже не меняя время. Как правило, не доверяйте клиенту, всегда проверяйте что-либо на сервере.

При этом вы можете также сохранить логику клиента c, но заставить сервер отказать (например, 404 или около того) доступ к файлу «неправильного дня» в зависимости от даты. Но вам понадобится серверный лог c, чтобы исключить злоупотребления на стороне клиента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...