Как отправить базовую аутентификацию с помощью axios

110

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

  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. Когда я делаю это с помощью Postman, есть возможность установить базовую аутентификацию; если я не заполню эти поля, он также вернет 401, но если я это сделаю, запрос будет успешным.

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

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

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

Эммануэль
источник

Ответы:

158

Для базовой аутентификации есть параметр auth:

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

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

Пример:

await axios.post(session_url, {}, {
  auth: {
    username: uname,
    password: pass
  }
});
luschn
источник
4
привет, как я могу установить это во всех вызовах axios? Мне нужно добавить базовую аутентификацию ко всем вызовам ajax. axios.defaults.auth = {имя пользователя: 'dd', пароль: '##'} у меня не работает.
hkg328
может это поможет: gist.github.com/EQuimper/dc5fe02dcaca4469091729e1313f78d1
luschn
кстати, вы также можете написать обертку вокруг аксиом для подобных вещей
luschn
Я сделал для этого обертку. но этот api дает мне ошибку 401
hkg328
1
@ hkg328 вам нужно закодировать строку username: password в base64, если вы хотите вручную установить заголовок. что-то вроде import btoa from 'btoa-lite'; токен = btoa (имя пользователя + ':' + пароль); затем установите заголовок «Базовый» + токен;
shrumm
55

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

axios.post (URL [, данные [, конфигурация]])

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

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');
});
Pillravi
источник
1
ЭТО ПОМОГЛО, СПАСИБО
superrcoop
1
Это должен быть принятый ответ. Принятый ответ - это просто дубликат документации.
Sinister Beard
5

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

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

CORS

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

Конфигурация Backend 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 с заголовком авторизации:

<!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>

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

Эрик Одет
источник
noob CORS вопрос, это используется только в разработке, не так ли?
Лен Джозеф
Нет, это также и в основном в производстве.
Эрик Одет
3

Пример (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

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

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

Юси
источник
3

Решение, предоставленное 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');
  });
Леонард Саерс
источник
1

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

const username = ''
const password = ''

const token = Buffer.from(`${username}:${password}`, 'utf8').toString('base64')

const url = 'https://...'
const data = {
...
}

axios.post(url, data, {
  headers: {
 'Authorization': `Basic ${token}`
},
})

Это сработало для меня. надеюсь, это поможет

Фоти М. Констан
источник