Переменные PHP $ _SESSION не работают в приложении ionic / angularjs

Информация о среде разработки:

  • Местное развитие
  • Сетевой диск настроен на моем сервере на моем ПК
  • Доступ к файлам сервера через путь к каталогу
  • Сервер содержит базы данных SQL, к которым файлы сервера обращаются и из

При загрузке приложения

Я настроил 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.

Проблемы

  • Первоначальная проблема заключалась в том, что переменные сеанса были пустыми в get_more_info.php. Это произошло потому, что он не возобновлял тот же сеанс, начатый на $scope.nginit();. Вместо этого он начинал новую.
  • Была поднята идея сохранить session_id, чтобы он мог возобновиться в том же сеансе, и это то, что я здесь сделал.
  • Первоначально я пытался установить session_id, вручную устанавливая его в верхней части моих файлов PHP, но я обратил внимание на то, что в этом нет необходимости, и он должен делать это автоматически, а это не так.

вы назначили $ UserObj-> user_id; сеансу и назначил $ UserData-> user_id; в пользовательские данные. Это нормально. Попробуйте использовать localstorage

Shibu 10.01.2019 13:35

@Chrisshi $user_data['user_id'] = $UserObj->user_id - это то, что передается с сервера, которое затем становится доступным для data.user на стороне клиента. localstorage можно использовать только на стороне клиента, и я пытаюсь использовать переменные $_SESSION на стороне сервера, чтобы иметь постоянный доступ к user_id, а не передавать user_id в качестве параметра каждый раз при выполнении $http.post или $http.get.

J.Do 10.01.2019 13:43

Вы можете сгенерировать токен во время регистрации и сохранить этот токен для пользователя в таблице. Используя этот токен, вы можете получить доступ к учетной записи пользователя

Shibu 10.01.2019 13:50

@cbaconnier Я обновил свой вопрос, включив в него возможное исправление. Я не знал, что вы имели в виду, передавая это в заголовок. Я попытался сделать это через http.get / post, но не смог заставить его работать, поэтому вместо этого я передал их через http params. Какая разница в том, что вы упомянули в моем решении? У вас есть пример, на который я могу посмотреть, чтобы понять, что вы имеете в виду?

J.Do 14.01.2019 14:43
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
4
894
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Бэкэнд

Во-первых: этот бит - ненужный:

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? Нужно ли мне изменить ключ параметра на конкретный?

J.Do 14.01.2019 17:57

@yivi, это отлично работает! Я объединил его с тем, какой пользователь / msphn ответил на него, поэтому мне не нужно вводить withCredentials: true для каждого запроса.

J.Do 15.01.2019 10:49

@ J.Do Это ваш выбор. Я скорее скажу об этом прямо, чтобы вы точно знали, для каких запросов вам нужна эта дополнительная информация. В противном случае у вас могут возникнуть проблемы с CORS в запросах, которые не требуют такой настройки.

yivi 15.01.2019 10:50

@yivi Понятно. Спасибо. Еще одна вещь, куда я поставил header( "Access-Control-Allow-Origin: http://localhost:8000" );. Будет ли порт хоста каждый раз одинаковым или он будет меняться?

J.Do 15.01.2019 10:52

@ J.Do хост и порт должен соответствовать везде, где вы обслуживаете приложение angular. В этом примере я использую localhost: 8000, потому что это то, что я использовал для своей локальной настройки. Если вы развертываете его в другом домене или на другом порту, разрешающее происхождение должно соответствовать тот.

yivi 15.01.2019 10:54

Привет, йиви. Когда я этим занимался, все было на android и все еще работает. Однако в настоящее время я пробую его для iOS с помощью симулятора iPhone, но PHPSESSID, похоже, изменился, вы знаете, почему это могло быть? Ничего не менял и на андроиде работает нормально. Я все еще изучаю это, но я подумал, что спрошу, если у вас есть идеи!

J.Do 05.02.2019 11:57

Чтобы использовать файлы cookie (которые необходимы для сеансов php), вы должны разрешить приложению это сделать.

Используйте это, чтобы настроить его глобально, после чего приложение будет использовать ваш файл cookie и повторно использовать его для других запросов.

.config(['$httpProvider', function($httpProvider) {
   $httpProvider.defaults.withCredentials = true;
}])

Я пробовал это, и теперь я получаю сообщение об ошибке Доступ к XMLHttpRequest в 'hostserver / файлы_сервера / страницы / login.php' из источника 'локальный: 8100' был заблокирован политикой CORS: ответ на предполетный запрос не проходит проверку контроля доступа: значение 'Access- Заголовок Control-Allow-Origin 'в ответе не должен содержать подстановочный знак' * ', если режим учетных данных запроса -' include '. Режим учетных данных запросов, инициированных XMLHttpRequest, контролируется атрибутом withCredentials.

J.Do 15.01.2019 10:17

Да, первый запрос относится к типу OPTIONS и спрашивает, чего ожидает сервер. После этого отправляется актуальный запрос. Запросы OPTIONS не допускают использование подстановочных знаков в разрешении происхождения. Таким образом, запросы OPTIONS отвечают только одним конкретным, а не списком, даже если вы проанализируете запрос и решите, какой из них вы хотите вернуть. Вы можете, например, проверьте список хостов, и если хост запроса находится в этом списке, вы вернете заголовок с именно этим хостом.

msphn 15.01.2019 10:35

@ J.Do В своем ответе я обращаюсь к звонку OPTIONS. Это предварительный вызов, выполняемый браузером. Вам необходимо правильно ответить на этот запрос. Вам также необходимо отправить обратно правильные заголовки CORS, как я показал в своем ответе.

yivi 15.01.2019 10:45

Другие вопросы по теме