Реагируйте на родные аксиозы, которые не проходят аутентификацию на apache / php - PullRequest
3 голосов
/ 24 июня 2019

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

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.log(`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, а не реагирующе-родным / axios.Я собрал экспресс-сервер, который имитировал ту же проверку, что и PHP: - Ищите заголовок авторизации - Распечатайте его - Верните обратно 403 или 200 с данными на основе этого

При запуске, указывая на http://localhost: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 был тегом.Существует множество статей по решению этой проблемы с помощью ReWriteMod на apache / zend, поэтому сначала я опробую их и посмотрю, решит ли это проблему.

** Edit 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

Resolved (ish)

1 Ответ

2 голосов
/ 27 июня 2019

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

Для тех, кто заинтересован: мы используем Django в качестве нашего бэкэнда и по умолчанию, когда вы делаете не предоставлять конечную косую черту в конечную точку, Django перенаправляет из не косой черты конечная точка к конечной точке косой черты.

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

OkHttp удаляет заголовок «Авторизация» при перенаправлении на хосты (соединения). через ответ 3xx от оригинального хоста.

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

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

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