Реагировать на собственный axios ios, не аутентифицирующийся в apache/php

Я публикую это по дороге домой, так что простите за отсутствие кода, но я постараюсь быть как можно более подробным и добавить код, когда смогу, сегодня вечером. По сути, у меня есть нативное приложение для реагирования, использующее избыточность и аксиомы. Краткий обзор (следующий код) может объяснить, что я делаю что-то не так.

Serviceapi.js Создает и экспортирует базовые аксиомы с базовым URL.

const ServiceApi = axios.create({
    baseURL: BASE_URL,
    responseType: 'json'
});

AuthReducer.js При входе в систему заголовок авторизации устанавливается вручную с помощью метода post. Это работает как на Android, так и на iOS, возвращается логин, и я использую заголовок авторизации.

return {
    type: PERFORM_LOGIN,
    payload: {
        user: {
            name: username
        },
        request: {
            url: '/login',
            method: 'post',
            headers: { 
                'Authorization': 'Basic ' + basicAuth
            }
        }
    }

При входе в систему я возвращаю следующее действие redux-axios, вы можете видеть, что я установил заголовок: Авторизация вручную, это прекрасно работает.

        // On login success, set the authInterceptor responsible for adding headers
        authInterceptor = ServiceApi.interceptors.request.use((config) => {
          console.info(`Attaching Authorization to header ${basicAuth}`);
          config.headers.common.Authorization = basicAuth;
          return config;
        }, (error) => {
          Promise.reject(error);
        });

При выходе из системы я очищаю перехватчик. Я решил добавлять и удалять при входе и выходе из системы вместо того, чтобы всегда иметь их там просто так. Это может быть проблемой, но для Android это нормально

// Clear the auth interceptor
ServiceApi.interceptors.request.eject(authInterceptor);

Опять же, все это отлично работает на Android. И, похоже, работает на ios. Когда я отлаживаю перехватчик, он вызывается и устанавливает заголовок.

Но я получаю обратно 403 на ios. Изучив запрос более подробно, можно заметить большую разницу между заголовком android в запросе и заголовком ios в запросе. Остальная часть объекта запроса одинакова, различается только объект _header между ios и android.

Android-запрос

    _headers:
        accept: "application/json, text/plain, */*"

        authorization: "Basic <correct base64 value>"

        content-type: "application/json;charset=utf-8"
__proto__: Object


Запрос IOS

    _headers:
        accept: (...)

        authorization: (...)

        content-type: (...)

        get accept: ƒ ()
        
set accept: ƒ ()

        get authorization: ƒ ()
        
set authorization: ƒ ()
        
get content-type: ƒ ()

        set content-type: ƒ ()

        __proto__: Object


С различиями, устанавливая точку останова при просмотре консоли для error.request._headers.authorization;, я получаю то же содержимое «Basic:», что и заголовок Android.

index.php Бэкэнд-сервис представляет собой файл php, который выполняет $_SERVER['PHP_AUTH_USER'], который завершается ошибкой 403, если не установлен, что и происходит. У меня нет доступа к php, мне только что сказали, что это то, что он использует.

Еще раз приношу извинения за то, что не предоставил код, но я сделаю это, когда у меня будет шанс позже. Может быть, мне нужно что-то дополнительно установить для ios? Или, может быть, php для ios нужен дополнительный заголовок?

Код для подражания.

РЕДАКТИРОВАТЬ Обновлено с кодом, надеюсь, я не оставил ни одной закодированной информации для входа.

РЕДАКТИРОВАТЬ 2 При дальнейшем расследовании похоже, что это связано с apache/PHP, а не с react-native/axios. Я собрал экспресс-сервер, который имитировал ту же проверку, что и PHP: - Найдите заголовок авторизации - Распечатать - Возврат обратно 403 или 200 с данными на основе этого

При запуске, указывающем на http://локальный: 3000, используя точно такое же приложение в эмуляторе, я получаю то, что ожидаю. Чтобы добавить к этому, когда я на эмуляторе, я не могу войти в действующий URL-адрес (хотя я мог бы на обычном устройстве), я получаю ту же ошибку 403, но на этот раз немного раньше.

РЕДАКТИРОВАТЬ 3

Чтобы предоставить дополнительную информацию с сервера, вот три запроса, которые мне удалось зарегистрировать:

1) Это из эмулятора IOS iPhone8 против экспресс-сервера:

accept:"application/json, text/plain, */*"
accept-encoding:"gzip, deflate"
accept-language:"en-us"
authorization:"Basic <base 64 encoding>"
connection:"keep-alive"
content-length:"0"
host:"localhost:3000"
user-agent:"MobileApp/1 CFNetwork/978.0.7 Darwin/18.5.

2) Это тот же эмулятор для apache/PHP (5.3.3), мы видим, что заголовок авторизации отсутствует.

Accept: application/json, text/plain, */*                                                             
User-Agent: MobileApp/1 CFNetwork/978.0.7 Darwin/18.5.0       
Accept-Language: en-us                                                    
Accept-Encoding: br, gzip, deflate                                        
Connection: keep-alive     

3) Это с Android на apache/PHP (5.3.3):

authorization: Basic <Base 64 encoding> 
Host: api.serviceurl.com
Connection: Keep-Alive                            
Accept-Encoding: gzip                                 
User-Agent: okhttp/3.12.1

Редактировать 4 Итак, поиграв некоторое время и погуглив, выяснилось, что проблема связана с Zend Framework и fastcgi, которые автоматически удаляют заголовок авторизации. Странно то, что он делает это только из IOS, а не из Android, что на самом деле не имеет смысла.

Что мы заметили в журналах, так это то, что он принимает Android и Postman как POST, но регистрирует запросы IOS как GET. Я не совсем уверен, что с этим, но, кажется, это еще одно отличие. Я обновил задачу, чтобы использовать zend в качестве тега. Существует ряд статей SO о решении этой проблемы с помощью ReWriteMod в apache/zend, поэтому я сначала попробую их и посмотрю, решит ли это проблему.

** Редактировать 5** До сих пор мы пытались следовать статьям SO, которые просят добавить следующее (Заголовок авторизации отсутствует в django rest_framework, виноват ли apache?):

SetEnvIfNoCase Authorization ^(.*) -e=PHP_HTTP_AUTH

RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

что приводит к следующему:

// IOS
_SERVER[PHP_HTTP_AUTH] = <blank>
_SERVER[HTTP_AUTHORIZATION] = <blank>

// Android
_SERVER[PHP_HTTP_AUTH] = Username
_SERVER[HTTP_AUTHORIZATION] = Basic <Base65 encoded>
_SERVER[PHP_HTTP_PW] = Password

Итак, мы знаем, что авторизация заголовков доходит до Apache, но теперь она проходит как пустая. Есть несколько других ответов SO, которые я изучаю, но поиск продолжается...

Изменить 6

Решено (иш)

Является ли URL-адрес, к которому вы подключаетесь, за http или https? Я помню, что в info.plist была настройка, которая указывает URL-адреса, к которым вы можете подключиться с помощью незащищенных вызовов. Может быть что-то в этом духе?

Tim Lewis 24.06.2019 23:00

https. Для входа используется тот же клиент axios. Единственная разница в том, что я делаю a. Опубликовать(/login, {headers:{}}) вручную. В то время как для всех остальных запросов я использую перехватчик. Я мог бы переписать клиент так, чтобы он постоянно устанавливал пользовательский проход вручную, но я решил, что лучше использовать перехватчик. Прошу прощения, я тоже сижу на телефоне еще пару часов. Так что простите за опечатки.

kendavidson 24.06.2019 23:20

Ах я вижу. Не могу сказать, что знаком с концепцией перехватчика в react-native. Это часть redux? Звучание все больше и больше похоже на это, будет легче отлаживать, когда код будет опубликован :)

Tim Lewis 24.06.2019 23:24

Перехватчик - вещь аксиома. Используя что-то похожее на gist.github.com/srph/38f67a10e991b6cb2d83 this. Но я установил перехватчик в действии редуктора LOGIN_SUCCESS вместо того, чтобы хранить его в клиентском файле asios. Я ценю внешний вид. Выложу код в т-минус перед сном.

kendavidson 24.06.2019 23:36
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
3
4
1 474
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Оказывается, это была косая черта в конце запроса для IOS. Мне удалось найти эту ссылку https://github.com/square/retrofit/issues/1037, где проблема была описана как:

For those interested: We are using Django as our backend and by default when you do not provide a trailing slash on the endpoint Django redirects from the non-slash endpoint to the slash endpoint.

Сейчас мы не используем Django, но, видимо, для нашей конфигурации Zend это было та же проблема - Android смог перенаправить без проблем, а IOS - нет. В другом комментарии к заданию говорится:

OkHttp strips the "Authorization" header when redirected across hosts (connections) via a 3xx response from the original host.

Что не кажется точным, так как Android использовал OkHttp и работал нормально. Похоже, у IOS, использующего Darwin, была проблема.

РЕДАКТИРОВАТЬ Я забыл еще кое-что из своего исходного поста, мне также пришлось изменить свой перехватчик со строки config.headers.common.Authorization = ... на config.headers.Authorization = ..., который почему-то сохранил корпус. Первоначальный способ преобразовал авторизацию в авторизацию, а последний сохранил ее как авторизацию. Не уверен, что это было проблемой, но я все равно сделал это.

// On login success, set the authInterceptor responsible for adding headers
authInterceptor = ServiceApi.interceptors.request.use((config) => {
      console.info(`Attaching Authorization to header ${basicAuth}`);
      config.headers.Authorization = basicAuth;
      return config;
    }, (error) => {
      Promise.reject(error);
    });

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