В сфере исполнительского искусства — там, где я работаю — многие сайты артистов и компаний имеют так называемую «профессиональную» зону, защищенную паролем часть веб-сайта, предназначенную для профессионалов отрасли или представителей прессы. Часто содержит примечания к программе, изображения с высоким разрешением, технических райдеров; все, чем компания захочет поделиться, только с некоторыми.
Недавно я реализовал такую профессиональную область для статического веб-сайта, размещенного на Netlify. В этой статье я расскажу вам о настройке, которую я создал для этого. Мы будем использовать бессерверные функции, перенаправления и отличную службу идентификации Netlify, чтобы скрыть определенные части статического сайта за паролем.
Содержание статьи
Требования
Мы хотим скрыть некоторые страницы за паролем, но нет необходимости в полноценной учетной записи пользователя. В конце концов, информация, которую мы хотим защитить, не привязана к конкретному пользователю; мы просто не хотим никому показывать это. Наш вариант использования очень похож на защищенное паролем видео на Vimeo, в котором посетителю нужен только пароль, а не учетная запись для доступа к частному ресурсу.
Тем не менее, мы огораживаем не отдельный ресурс, а территорию. Посетителю не нужно вводить пароль на каждой странице в защищенной части сайта. Пройдя через дверь, они могут свободно передвигаться. Это сложная часть, поскольку статические сайты не имеют доступа к сеансам для сохранения состояния.
Наконец, я хотел, чтобы это работало без какого-либо клиентского JavaScript. Это означает, что мы не можем получать данные для динамического заполнения наших защищенных страниц, что в противном случае могло бы стать жизнеспособной стратегией.
Кодирование по
Я создал стартовый репозиторий для всех, кто хотел бы следить за тем, как мы кодируем и настраиваем эту функциональность. Вы можете развернуть чистый сайт в Netlify одним нажатием кнопки. Каждый раз, когда вы фиксируете и отправляете изменения в свою копию репозитория, сайт будет повторно развернут.
Контроль доступа на основе ролей
Мы предоставляем доступ посетителям в зависимости от их роли, от того, являются ли они «профи». Поэтому ролевой контроль доступа Netlify приходит на ум как подходящий инструмент для защиты страниц. Назначая определенные роли определенным пользователям, мы можем перенаправлять их в разные области сайта.
Netlify позволяет устанавливать правила перенаправления с условием Role
. Вы можете добавить файл _redirects
в общий каталог или использовать альтернативный синтаксис для файла конфигурации netlify.toml
в корневом каталоге. Здесь я покажу последнее. Добавьте это в файл TOML:
[ [ перенаправляет ] ]
из = "/ pro / *"
статус = 200
сила = истина
условия = { Роль = [ "за" ] } [ [ перенаправляет ] ]
из = ] "/ pro / *"
до = "/ логин /"
статус ] = 302
сила = истина
Сначала посмотрите на нижнее правило. Это указывает Netlify перенаправлять любые запросы страниц из каталога / pro /
на страницу / login /
. Если только не сработает верхнее правило, которое позволяет посетителям получать доступ к профессиональным страницам, если у них установлен правильный набор ролей. Обратите внимание, как мы принудительно перенаправляем
. Без этого параметра Netlify игнорирует любые перенаправления с реально существующих страниц. Если все пойдет хорошо, вы больше не сможете добраться до зоны профи.
Теперь, как нам установить это свойство Role
? Используя JSON Web Tokens, вкратце JWT. Вы можете думать о JWT как о зашифрованных учетных данных, которые мы будем хранить как файл cookie во внешнем интерфейсе. При каждом запросе страницы Netlify ищет файл cookie nf_jwt
. Если присутствует, cookie с JWT декодируется и читается. Результирующий объект JSON определяет, приписывает ли Netlify роль посетителю и, следовательно, произойдет ли перенаправление на основе ролей.
Мы воспользуемся Netlify Identity для генерации токенов аутентификации.
Настройка Netlify Identity
Netlify Identity — это сервис для управления и аутентификации пользователей на вашем сайте. Хотя нам не нужны учетные записи пользователей с именем пользователя и паролем, мы можем перепрофилировать сервис для создания входов только с паролем. Мы создадим одного пользователя. Когда посетитель пытается войти в систему, он сообщит пароль, а мы введем для него имя пользователя.
Во-первых, нам нужно включить службу на панели управления сайта на вкладке «Идентификация». Уровень бесплатного пользования допускает до 1000 пользователей, так что у нас все должно быть хорошо.





Мы подключимся к другой конечной точке GoTrue, / token
чтобы создать наш токен доступа. Поскольку мы не используем JavaScript во внешнем интерфейсе и не хотим раскрывать имя пользователя, мы прибегнем к бессерверной функции для согласования создания токена за нас.
Добавьте форму на страницу входа:
< форма действие = " /. Netlify / functions / login " метод = " POST " >
< ярлык для = " пароль " > Пароль </ метка >
< ввод тип = " пароль " имя = " пароль " id = « пароль » />
] < кнопка тип = " отправить " > Получить доступ </ кнопка >
</ форма >
Когда посетитель нажимает кнопку отправки, функция входа
получит пароль. Давайте создадим эту функцию.
Добавьте в свой проект папку functions
и создайте внутри login.js
. Затем сообщите Netlify, где найти нашу функцию. Прикрепите эти строки к своей конфигурации netlify.toml
:
[ функции ]
каталог = "функции"
Мы отправим запрос в нашей функции, поэтому мы установим axios
. В своем проекте запустите:
npm init -y
npm установить axios
Откройте функцию входа в систему и добавьте некоторые функции:
const querystring = require ( 'querystring ' ) ;
const axios = require ( 'axios' ) ; экспорт . обработчик = async функция ( событие контекст ) {
const { пароль } = querystring . parse ( событие . тело ) ;
const конечная точка = ` $ { процесс . env . URL } /. Netlify / identity / token ` ;
const data = querystring . stringify ( {
grant_type : ] 'пароль'
имя пользователя : 'email@example.com'
пароль : пароль
} ) ;
const варианты = {
заголовки : {
'Content-Type' : 'application / x-www-form-urlencoded'
}
} ;
try {
const response = await axios . post ( конечная точка данные варианты ) ;
const access_token = response . data . access_token ;
return {
statusCode : 302
заголовки : {
'Set-Cookie' : ` nf_jwt = $ { access_token } ; Путь = /; HttpOnly; Безопасный «
'Контроль кеша' : 'без кеширования'
Местоположение : '/ pro /'
}
} ;
} поймать ( ошибка ]) {
консоль . журнал ( ошибка ) ;
return {
statusCode : 302
заголовки ]: {
«Управление кешем» : «без кеша»
Местоположение : '/ login /'
}
} ; ]
}
} ;
Давайте рассмотрим это. Сначала мы получаем пароль из формы. Затем мы создаем URL-адрес конечной точки и формируем данные аутентификации в соответствии с ожидаемой конечной точкой / токен
; что-то вроде grant_type=password&username=email@example.com&password=secret
. Выполните запрос и получите токен доступа из ответа. Затем мы перенаправляем посетителя на страницу / pro /
устанавливая файл cookie nf_jwt
с нашим токеном JWT. Флаги HttpOnly
и Secure
повышают безопасность, поскольку наши файлы cookie не могут быть перехвачены при незащищенных соединениях или изменены на стороне клиента.
Если пароль неправильный, посетитель возвращается на страницу входа. Без сообщения об ошибке или каких-либо указаний на то, что пошло не так, это не лучший пользовательский интерфейс. Но именно здесь JavaScript может вмешаться, чтобы улучшить ситуацию. По крайней мере, есть рабочий базовый уровень, когда скрипты отключены.
Токен JWT действителен в течение одного часа, а файл cookie устанавливается на время сеанса. Таким образом, наш посетитель может просматривать профессиональную зону в течение самого короткого из этих периодов. После этого они должны снова ввести пароль. Это отлично подходит для моего случая использования. Если вы хотите обновить токен, чтобы посетитель оставался в системе, вам также необходимо сохранить токен обновления и выполнить дополнительные запросы к GoTrue API.
Запоминание целевой страницы
Сейчас охраняемая территория состоит всего из одной страницы. Когда посетитель пытается получить доступ к маршруту / pro /
он перенаправляется на страницу входа, которая, в свою очередь, перенаправляет его обратно на / pro /
. Если у нас будет еще пара страниц, вложенных в каталог / pro /
жестко запрограммированное перенаправление в нашей функции входа в систему может оказаться не таким уж большим. Если посетитель делает закладки, скажем, / pro / nested /
он, вероятно, ожидает вернуться туда после входа в систему. Мы должны как-то вспомнить страницу, которую они пытались посетить.
Строки запроса — хороший инструмент для этого. Вместо перенаправления на / login /
URL теперь будет иметь вид / login /? Return = path-to-the-target-page
. Моей первой интуицией было попробовать следующее:
[ [ перенаправляет ] ]
от = "/ pro / *"
до = "/ login /? return = / pro /: splat"
status = 302
force = верно
: splat
соответствует тому, что соответствует подстановочному знаку *
. Для / pro / nested /
: splat
будет равняться nested /
. Это работает, но мы должны избегать косых черт в строке запроса. К счастью, функции Netlify снова могут нам помочь.
Создайте еще одну функцию, redirect.js
со следующим содержимым:
экспорт . обработчик = асинхронный ( событие ) => {
const путь = encodeURIComponent ( событие . путь ) ; return {
statusCode : 302
заголовки : {
Местоположение : ` / login /? Redirect = $ { путь } ] `
}
} ;
} ;
И измените второй редирект в netlify.toml
чтобы он выглядел так:
[ [ перенаправляет ] ]
с = "/ pro / *"
до = "/.netlify/functions/redirect"</functions/redirect"[19459014inventory[19459016inventory[19459017impressionstatus = 200
сила ]" = верно
Что здесь происходит? Посетители, не прошедшие аутентификацию, попадут в нашу недавно созданную функцию перенаправления, но по URL-адресу, который они пытались достичь. Параметр path
в нашей функции перенаправления будет указывать, например, на / pro / nested /
. Затем мы можем избежать фрагмента пути и добавить его в качестве параметра запроса к перенаправлению / login /
. Посетитель перейдет к / login /? Redirect =% 2Fpro% 2Fnested% 2F
.
Мы должны обновить нашу функцию входа в систему, чтобы обрабатывать динамическое перенаправление. Мы возьмем параметр перенаправления из URL-адреса и установим его как Местоположение
для нашего перенаправления. Я оставил / pro /
на случай отсутствия строки запроса.
const { перенаправление } = querystring . parse ( event . заголовки . referer . split ] ( '?' ) [ 1 ] ) ;
return {
statusCode : 302 ,
заголовки : {
'Set-Cookie' : ` nf_jwt = $ { access_token } ; Путь = /; HttpOnly; Безопасный «
'Контроль кеша' : 'без кеширования'
Местоположение : перенаправление || '/ pro /'
] }
} ;
возврат {
statusCode : 302
заголовки : {
] «Контроль кеша» : «без кеша»
Местоположение : ` / login /? Redirect = $ { encodeURIComponent ( перенаправление ) } `
}
} ];
Это должно сработать. Вот демонстрация того, что мы построили. Пароль «секретный». Вы можете найти полный код на Github.
Заключение
Используя пояс инструментов, который Netlify предоставляет с его функциями, перенаправлениями и API аутентификации, мы можем скрыть части статического веб-сайта за паролем.