Как отправить Basic Auth с помощью axios

Я пытаюсь реализовать следующий код, но что-то не работает. Вот код:

  var session_url = 'http://api_address/api/session_endpoint';
  var username = 'user';
  var password = 'password';
  var credentials = btoa(username + ':' + password);
  var basicAuth = 'Basic ' + credentials;
  axios.post(session_url, {
    headers: { 'Authorization': + basicAuth }
  }).then(function(response) {
    console.log('Authenticated');
  }).catch(function(error) {
    console.log('Error on Authentication');
  });

Возвращает ошибку 401. Когда я делаю это с почтальоном, есть возможность установить Basic Auth; если я не заполняю эти поля, он также возвращает 401, но если я это сделаю, запрос будет успешным.

Есть идеи, что я делаю не так?

Вот часть документов API о том, как реализовать это:

Эта служба использует информацию базовой аутентификации в заголовке для установления сеанса пользователя. Учетные данные проверяются на сервере. Использование этого веб-сервиса создаст сеанс с переданными учетными данными пользователя и вернет JSESSIONID. Этот JSESSIONID может использоваться в последующих запросах для выполнения вызовов веб-службы. *

Ответ 1

Существует параметр "auth" для Basic Auth:

auth: {
    username: 'janedoe',
    password: 's00pers3cret'
}

Источник/Документы: https://github.com/mzabriskie/axios

Ответ 2

Причина, по которой код в вашем вопросе не проходит проверку подлинности, заключается в том, что вы отправляете аутентификацию в объекте данных, а не в конфиге, который поместит его в заголовки. Согласно документам axios, псевдоним метода запроса для post:

axios.post(url [, data [, config]])

Поэтому, чтобы ваш код работал, вам нужно отправить пустой объект для данных:

var session_url = 'http://api_address/api/session_endpoint';
var username = 'user';
var password = 'password';
var basicAuth = 'Basic ' + btoa(username + ':' + password);
axios.post(session_url, {}, {
  headers: { 'Authorization': + basicAuth }
}).then(function(response) {
  console.log('Authenticated');
}).catch(function(error) {
  console.log('Error on Authentication');
});

То же самое верно для использования параметра auth, упомянутого @luschn. Следующий код эквивалентен, но использует вместо этого параметр auth (а также передает пустой объект данных):

var session_url = 'http://api_address/api/session_endpoint';
var uname = 'user';
var pass = 'password';
axios.post(session_url, {}, {
  auth: {
    username: uname,
    password: pass
  }
}).then(function(response) {
  console.log('Authenticated');
}).catch(function(error) {
  console.log('Error on Authentication');
});

Ответ 3

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

  1. CORS (если вы используете внешний и внутренний интерфейсы в разных доменах и портах.
  2. Конфигурация внутреннего интерфейса CORS
  3. Базовая конфигурация аутентификации Axios

CORS

Моя установка для разработки выполняется с помощью приложения vuejs webpack, работающего на localhost: 8081, и приложения весенней загрузки, работающего на localhost: 8080. Поэтому при попытке вызвать rest API из внешнего интерфейса браузер не позволит мне получить ответ от весеннего бэкэнда без надлежащих настроек CORS. CORS можно использовать для ослабления защиты кросс-доменных скриптов (XSS), которую имеют современные браузеры. Насколько я понимаю, браузеры защищают ваш SPA от атаки XSS. Конечно, в некоторых ответах на StackOverflow предлагалось добавить плагин chrome для отключения защиты XSS, но это действительно работает И если бы это было так, это только подтолкнуло бы неизбежную проблему на потом.

Конфигурация серверной части CORS

Вот как вы должны настроить CORS в своем весеннем загрузочном приложении:

Добавьте класс CorsFilter, чтобы добавить правильные заголовки в ответ на запрос клиента. Access-Control-Allow-Origin и Access-Control-Allow-Headers являются наиболее важной вещью для базовой аутентификации.

    public class CorsFilter implements Filter {

...
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        response.setHeader("Access-Control-Allow-Origin", "http://localhost:8081");
        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
        **response.setHeader("Access-Control-Allow-Headers", "authorization, Content-Type");**
        response.setHeader("Access-Control-Max-Age", "3600");

        filterChain.doFilter(servletRequest, servletResponse);

    }
...
}

Добавьте класс конфигурации, который расширяет Spring WebSecurityConfigurationAdapter. В этом классе вы внедрите свой фильтр CORS:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
    @Bean
    CorsFilter corsFilter() {
        CorsFilter filter = new CorsFilter();
        return filter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.addFilterBefore(corsFilter(), SessionManagementFilter.class) //adds your custom CorsFilter
          .csrf()
          .disable()
          .authorizeRequests()
          .antMatchers("/api/login")
          .permitAll()
          .anyRequest()
          .authenticated()
          .and()
          .httpBasic()
          .authenticationEntryPoint(authenticationEntryPoint)
          .and()
          .authenticationProvider(getProvider());
    }
...
}

Вам не нужно помещать что-либо связанное с CORS в ваш контроллер.

Внешний интерфейс

Теперь во внешнем интерфейсе вам нужно создать свой запрос axios с заголовком Authorization:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://unpkg.com/vue"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
    <p>{{ status }}</p>
</div>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            status: ''
        },
        created: function () {
            this.getBackendResource();
        },
        methods: {
            getBackendResource: function () {
                this.status = 'Loading...';
                var vm = this;
                var user = "aUserName";
                var pass = "aPassword";
                var url = 'http://localhost:8080/api/resource';

                var authorizationBasic = window.btoa(user + ':' + pass);
                var config = {
                    "headers": {
                        "Authorization": "Basic " + authorizationBasic
                    }
                };
                axios.get(url, config)
                    .then(function (response) {
                        vm.status = response.data[0];
                    })
                    .catch(function (error) {
                        vm.status = 'An error occured.' + error;
                    })
            }
        }
    })
</script>
</body>
</html>

Надеюсь это поможет.

Ответ 4

Решение, предоставленное luschn и pillravi, работает нормально, если вы не получите в ответе заголовок Strict-Transport-Security.

Добавление withCredentials: true решит эту проблему.

  axios.post(session_url, {
    withCredentials: true,
    headers: {
      "Accept": "application/json",
      "Content-Type": "application/json"
    }
  },{
    auth: {
      username: "USERNAME",
      password: "PASSWORD"
  }}).then(function(response) {
    console.log('Authenticated');
  }).catch(function(error) {
    console.log('Error on Authentication');
  });

Ответ 5

Пример (axios_example.js) с использованием Axios в Node.js:

const axios = require('axios');
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;

app.get('/search', function(req, res) {
    let query = req.query.queryStr;
    let url = 'https://your.service.org?query=${query}';

    axios({
        method:'get',
        url,
        auth: {
            username: 'xxxxxxxxxxxxx',
            password: 'xxxxxxxxxxxxx'
        }
    })
    .then(function (response) {
        res.send(JSON.stringify(response.data));
    })
    .catch(function (error) {
        console.log(error);
    });
});

var server = app.listen(port);

Убедитесь, что в вашем каталоге проекта вы делаете:

npm init
npm install express
npm install axios
node axios_example.js

Затем вы можете протестировать API REST Node.js, используя свой браузер по адресу: http://localhost:5000/search?queryStr=xxxxxxxxx

Ссылка: https://github.com/axios/axios