Ответ 1
С полномочиями контролирует настройку и отправку файлов cookie, поэтому не забудьте включить его при публикации для входа, чтобы возвращенный файл cookie был сохранен в браузере.
В течение нескольких дней я искал механизм безопасной проверки подлинности и управления сеансом для моего одностраничного приложения. Судя по многочисленным учебникам и сообщениям в блогах о SPA-процедурах и аутентификации, хранение JWT в localStorage или обычных куках, по-видимому, является наиболее распространенным подходом, но это просто не хорошая идея использовать JWT для сеансов, поэтому это не вариант для этого приложения.
Требования
Идеальный механизм, по-видимому, является аутентификацией на основе файлов cookie с использованием HttpOnly
файлов cookie, содержащих идентификаторы сеанса. Поток будет работать следующим образом:
HttpOnly
.withCredentials
.Поскольку cookie имеет флаг HttpOnly
, JavaScript не сможет прочитать его содержимое, поэтому он будет безопасен от атак, пока он передается через HTTPS.
Проблемы
Вот конкретная проблема, с которой я столкнулся. Мой сервер настроен для обработки запросов CORS. После аутентификации пользователя он правильно отправляет файл cookie в ответ:
HTTP/1.1 200 OK
server: Cowboy
date: Wed, 15 Mar 2017 22:35:46 GMT
content-length: 59
set-cookie: _myapp_key=SFMyNTYBbQAAABBn; path=/; HttpOnly
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
x-request-id: qi2q2rtt7mpi9u9c703tp7idmfg4qs6o
access-control-allow-origin: http://localhost:8080
access-control-expose-headers:
access-control-allow-credentials: true
vary: Origin
Однако браузер не сохраняет файл cookie (когда я проверяю локальные файлы cookie Chrome, он не существует). Поэтому, когда выполняется следующий код:
context.axios.post(LOGIN_URL, creds).then(response => {
context.$router.push("/api/account")
}
Создается страница учетной записи:
created() {
this.axios.get(SERVER_URL + "/api/account/", {withCredentials: true}).then(response => {
//do stuff
}
}
Этот вызов не содержит cookie в заголовке. Поэтому сервер отклоняет его.
GET /api/account/ HTTP/1.1
Host: localhost:4000
Connection: keep-alive
Accept: application/json
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Referer: http://localhost:8080/
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-US,en;q=0.8,tr;q=0.6
Нужно ли делать что-то особенное, чтобы браузер сохранял cookie после получения его в ответе на вход? Различные источники, которые я прочитал, сказали, что браузеры сохраняют файлы ответов cookie только тогда, когда пользователь перенаправляется, но я не хочу никаких "жестких" перенаправлений, поскольку это SPA.
Рассматриваемый SPA-код написан на Vue.js, но, я думаю, это относится ко всем SPA. Мне интересно, как люди справляются с этим сценарием.
Другие материалы, которые я прочитал по этой теме:
С полномочиями контролирует настройку и отправку файлов cookie, поэтому не забудьте включить его при публикации для входа, чтобы возвращенный файл cookie был сохранен в браузере.
Я получил эту работу на Vue.js 2 с credentials = true. Установка учетных данных с сайта клиента только наполовину. Вам также необходимо установить заголовки ответов с сервера:
header("Access-Control-Allow-Origin: http://localhost:8080");
header("Access-Control-Allow-Credentials: true");
Вы не можете использовать подстановочный знак для Access-Control-Allow-Origin следующим образом:
header("Access-Control-Allow-Origin: *");
Когда вы указываете заголовок credentials: true, вам необходимо указать orgin.
Как вы можете видеть, это PHP-код, вы можете смоделировать его на NodeJS или на любом языке сценариев на стороне сервера, который вы используете.
В VueJS я устанавливаю учетные данные = true, как это в main.js:
Vue.http.options.credentials = true
В компоненте я успешно выполнил вход с помощью ajax:
<template>
<div id="userprofile">
<h2>User profile</h2>
{{init()}}
</div>
</template>
<script>
export default {
name: 'UserProfile',
methods: {
init: function() {
// loggin in
console.log('Attempting to login');
this.$http.get('https://localhost/api/login.php')
.then(resource => {
// logging response - Notice I don't send any user or password for testing purposes
});
// check the user profile
console.log('Getting user profile');
this.$http.get('https://localhost/api/userprofile.php')
.then(resource => {
console.log(resource.data);
})
}
}
}
</script>
На стороне сервера все довольно просто: Login.php устанавливает cookie без какой-либо проверки (Примечание: это делается только для целей тестирования. Вам не рекомендуется использовать этот код в процессе производства без проверки)
<?php
header("Access-Control-Allow-Origin: http://localhost:8080");
header("Access-Control-Allow-Credentials: true");
$cookie = setcookie('user', 'student', time()+3600, '/', 'localhost', false , true);
if($cookie){
echo "Logged in";
}else{
echo "Can't set a cookie";
}
Наконец, userprofile.php просто проверяет, установлен ли файл cookie =
<?php
header("Access-Control-Allow-Origin: http://localhost:8080");
header("Access-Control-Allow-Credentials: true");
if(isset($_COOKIE['user'])){
echo "Congratulations the user is ". $_COOKIE['user'];
}else{
echo "Not allowed to access";
}
Успешно вошел в систему