Информация о среде разработки:
При загрузке приложения
Я настроил ng-init на своей странице для запуска функции $scope.nginit();, которая отправляет запрос $ _GET в файл моего сервера с именем login.php:
$http.get(url + "server/login.php",
{ transformResponse: [] })
.success(function(data, status, headers, config)
{
data = JSON.parse(data);
window.localStorage.setItem("session_id",data.session_id);
})
.error( function(data, status, headers, config)
{
console.info("Error: " + data + "; " + status);
});
Это включено в каждый из моих файлов сервера вверху страницы:
// if (isset($_GET['session_id'])) {
// session_id($_GET['session_id']);
// } else if (isset($_POST['session_id'])) {
// session_id($_POST['session_id']);
// }
session_start();
include_once "../scripts/masterscript.php";
header("Access-Control-Allow-Origin: *");
$connection = connect_to_database();
try
{
if ($_SERVER['REQUEST_METHOD'] != 'POST')
{
setup_form();
}
else
{
process_form();
}
sqlsrv_close($connection);
}
catch (Exception $e)
{
exit("Exception $e->getMessage()");
}
Вот setup_form () на login.php:
function setup_form()
{
global $connection;
header('Content-Type: application/json');
$user_data = array();
$user_data["session_id"] = session_id();
echo json_encode($user_data);
}
В submitForm (); для входа в систему:
Он добавляет session_id, хранящийся в localStorage, в качестве параметра, чтобы его можно было вернуть в сеанс PHP. Он устанавливает его поверх файла PHP, но этот раздел в настоящее время закомментирован.
Я намерен, если это пользователь-администратор, запустить второй $ http.request и открыть модальное окно.
$http.post(url + "pages/login.php", data_string,
{ headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;' },
params : { 'session_id' : window.localStorage.session_id }})
.success(function(data, status, headers, config)
{
var data = data[0];
if (data.is_admin)
{
$http.get(url + "server/get_more_info.php",
{ params : {'user_id' : data.user_id },
transformResponse: [] })
.success(function(data, status, headers, config)
{
// setup to open a modal
})
.error( function(data, status, headers, config)
{
});
}
})
.error( function(data, status, headers, config)
{
});
Поскольку это запрос $ _POST, он перейдет к process_form (), и вот он:
function process_form()
{
global $connection;
header('Content-Type: application/json');
$user_data = array();
$data_string = file_get_contents("php://input");
$data = json_decode($data_string);
$user_data['status_msg'] = "Error";
// runs SQL query, grabs user details where email = $data->email
$UserObj = new User(0,$connection, $data->email);
if ($UserObj->password == $data->password)
{
$user_data['status_msg'] = "OK";
$user_data['user_id'] = $UserObj->user_id;
$user_data['user_type'] = $UserObj->user_type;
if ($UserObj->admin_user == 1)
{
$user_data['is_admin'] = true;
$_SESSION['is_admin'] = 1;
}
$_SESSION['user_id'] = $UserObj->user_id;
$_SESSION['user_type'] = $UserObj->user_type;
}
unset($UserObj);
echo json_encode($user_data);
}
В get_more_info.php
Я пытаюсь получить доступ к переменным сеанса, установленным в login.php, но они пустые. Я намерен использовать эти переменные в SQL-запросах:
$user_id = $_SESSION['user_id'];
$admin_user = $_SESSION['admin_user'];
$user_type = $_SESSION['user_type'];
$sql = " select * from info_table where admin_user = ? and user_type = ?";
$params = array($admin_user,$user_type);
$result = sqlsrv_query($connection, $sql, $params);
while($row = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC))
{
}
sqlsrv_free_stmt($result);
unset($result);
Дополнительная информация
Я сделал var_dump (); для обоих из них ниже и возвращают пустые строки.
ini_get('session.cookie_httponly');
ini_get('session.cookie_secure');
В Firefox появляется первый сетевой запрос для login.php, который является запросом GET и имеет набор $ _COOKIE. Кажется, что он работает в хроме, но не в firefox. В настоящее время я просто использую ionic serve --lab. В Chrome он продолжается и открывает модальное окно, как и должно, но в Firefox этого не происходит.
На вкладке сети firefox для запроса login.php GET он показывает
set-cookie в заголовках ответов, но не имеет атрибута cookie в заголовках запросов.
Для запроса POST login.php он имеет тот же результат, что и предыдущий для файла cookie, но этот запрос отображается как метод OPTIONS на вкладке сети вместо POST.
Проблемы
$scope.nginit();. Вместо этого он начинал новую.@Chrisshi $user_data['user_id'] = $UserObj->user_id - это то, что передается с сервера, которое затем становится доступным для data.user на стороне клиента. localstorage можно использовать только на стороне клиента, и я пытаюсь использовать переменные $_SESSION на стороне сервера, чтобы иметь постоянный доступ к user_id, а не передавать user_id в качестве параметра каждый раз при выполнении $http.post или $http.get.
Вы можете сгенерировать токен во время регистрации и сохранить этот токен для пользователя в таблице. Используя этот токен, вы можете получить доступ к учетной записи пользователя
@cbaconnier Я обновил свой вопрос, включив в него возможное исправление. Я не знал, что вы имели в виду, передавая это в заголовок. Я попытался сделать это через http.get / post, но не смог заставить его работать, поэтому вместо этого я передал их через http params. Какая разница в том, что вы упомянули в моем решении? У вас есть пример, на который я могу посмотреть, чтобы понять, что вы имеете в виду?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


if (isset($_GET['session_id'])) {
session_id($_GET['session_id']);
} else if (isset($_POST['session_id'])) {
session_id($_POST['session_id']);
}
Единственная строка, которая вам нужна в начале вашего файла more_details.php, - это session_start().
Если вы посмотрите на документация для этой функции, там ясно сказано:
session_start() creates a session or resumes (*) the current one based on a session identifier passed via a GET or POST request, or passed via a cookie.
* emphasis mine
Поэтому после его вызова вы можете безопасно получить доступ к свойствам $_SESSION.
Во-вторых, вам необходимо настроить правильные заголовки CORS.
header("Access-Control-Allow-Origin: http://localhost:8000");
header("Access-Control-Allow-Headers: content-type, authorization");
header("Access-Control-Allow-Credentials: true");
Очень важно: Access-Control-Allow-Origin не может быть установлен на *, иначе это не удастся. При использовании credentials разрешенное происхождение необходимо указать явно.
Кроме того, вам необходимо учитывать вызов OPTIONS, который должен возвращать те же заголовки. Этот вызов будет выполнен браузером в качестве предполетной проверки перед запросом POST.
Для этого ответа у меня есть файл common.php:
<?php
session_start();
header( "Access-Control-Allow-Origin: http://localhost:8000" );
header( 'Content-Type: application/json' );
header( "Access-Control-Allow-Headers: content-type,authorization" );
header( "Access-Control-Allow-Credentials: true" );
if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) {
die();
}
Другой файл one.php:
<?php
// one.php
<?php
require 'common.php';
$was_session_set = $_SESSION['user_id'] ?? 'no session id yet';
$_SESSION['user_id'] = microtime( true );
echo '{"session": "' . $was_session_set . '"}';
die();
Другой two.php:
<?php
require 'common.php';
$user_id = $_SESSION['user_id'] ?? 0;
echo '{"session": "' . $user_id .'"}';
die();
let app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope, $http) {
$http.get("http://localhost:8006/one.php", { withCredentials: true })
.then(function (response) {
$scope.myWelcome = response.data;
$http.post("http://localhost:8006/two.php", { withCredentials: true })
.then(function (response2) {
console.info(response2.data);
})
});
});
Спасибо за ответ. Я только что удалил ручную настройку session_id в верхней части моих файлов, но теперь она перестала работать. Я передаю session_id, когда запускаю запрос http.get, и передаю его через параметр $http.get(url + "server/get_more_info.php", { params : {'session_id' : window.localStorage.session_id}, transformResponse: [] }). Как узнать, какой параметр применить к session_id? Нужно ли мне изменить ключ параметра на конкретный?
@yivi, это отлично работает! Я объединил его с тем, какой пользователь / msphn ответил на него, поэтому мне не нужно вводить withCredentials: true для каждого запроса.
@ J.Do Это ваш выбор. Я скорее скажу об этом прямо, чтобы вы точно знали, для каких запросов вам нужна эта дополнительная информация. В противном случае у вас могут возникнуть проблемы с CORS в запросах, которые не требуют такой настройки.
@yivi Понятно. Спасибо. Еще одна вещь, куда я поставил header( "Access-Control-Allow-Origin: http://localhost:8000" );. Будет ли порт хоста каждый раз одинаковым или он будет меняться?
@ J.Do хост и порт должен соответствовать везде, где вы обслуживаете приложение angular. В этом примере я использую localhost: 8000, потому что это то, что я использовал для своей локальной настройки. Если вы развертываете его в другом домене или на другом порту, разрешающее происхождение должно соответствовать тот.
Привет, йиви. Когда я этим занимался, все было на android и все еще работает. Однако в настоящее время я пробую его для iOS с помощью симулятора iPhone, но PHPSESSID, похоже, изменился, вы знаете, почему это могло быть? Ничего не менял и на андроиде работает нормально. Я все еще изучаю это, но я подумал, что спрошу, если у вас есть идеи!
Чтобы использовать файлы cookie (которые необходимы для сеансов php), вы должны разрешить приложению это сделать.
Используйте это, чтобы настроить его глобально, после чего приложение будет использовать ваш файл cookie и повторно использовать его для других запросов.
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.withCredentials = true;
}])
Я пробовал это, и теперь я получаю сообщение об ошибке Доступ к XMLHttpRequest в 'hostserver / файлы_сервера / страницы / login.php' из источника 'локальный: 8100' был заблокирован политикой CORS: ответ на предполетный запрос не проходит проверку контроля доступа: значение 'Access- Заголовок Control-Allow-Origin 'в ответе не должен содержать подстановочный знак' * ', если режим учетных данных запроса -' include '. Режим учетных данных запросов, инициированных XMLHttpRequest, контролируется атрибутом withCredentials.
Да, первый запрос относится к типу OPTIONS и спрашивает, чего ожидает сервер. После этого отправляется актуальный запрос. Запросы OPTIONS не допускают использование подстановочных знаков в разрешении происхождения. Таким образом, запросы OPTIONS отвечают только одним конкретным, а не списком, даже если вы проанализируете запрос и решите, какой из них вы хотите вернуть. Вы можете, например, проверьте список хостов, и если хост запроса находится в этом списке, вы вернете заголовок с именно этим хостом.
@ J.Do В своем ответе я обращаюсь к звонку OPTIONS. Это предварительный вызов, выполняемый браузером. Вам необходимо правильно ответить на этот запрос. Вам также необходимо отправить обратно правильные заголовки CORS, как я показал в своем ответе.
вы назначили $ UserObj-> user_id; сеансу и назначил $ UserData-> user_id; в пользовательские данные. Это нормально. Попробуйте использовать localstorage