Jak wysłać Basic Auth z axios

109

Próbuję zaimplementować następujący kod, ale coś nie działa. Oto kod:

  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');
  });

Zwraca błąd 401. Kiedy robię to z Postmanem, jest opcja ustawienia podstawowego uwierzytelniania; jeśli nie wypełnię tych pól, zwraca również 401, ale jeśli to zrobię, żądanie się powiedzie.

Jakieś pomysły, co robię źle?

Oto część dokumentacji API, jak to zaimplementować:

Ta usługa używa informacji o podstawowym uwierzytelnieniu w nagłówku do ustanowienia sesji użytkownika. Poświadczenia są sprawdzane na serwerze. Użycie tej usługi internetowej utworzy sesję z przekazanymi poświadczeniami użytkownika i zwróci JSESSIONID. Ten identyfikator JSESSIONID może być używany w kolejnych żądaniach wywołań usług internetowych. *

Emmanuel
źródło

Odpowiedzi:

155

Istnieje parametr „auth” dla podstawowego uwierzytelniania:

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

Źródło / Dokumenty: https://github.com/mzabriskie/axios

Przykład:

await axios.post(session_url, {}, {
  auth: {
    username: uname,
    password: pass
  }
});
luschn
źródło
4
cześć, jak mogę to ustawić we wszystkich wywołaniach axios? Muszę dodać podstawowe uwierzytelnianie do wszystkich wywołań ajax. axios.defaults.auth = {nazwa użytkownika: 'dd', hasło: '##'} to nie działa dla mnie.
hkg328
przy okazji, możesz też napisać opakowanie wokół axiosów na takie rzeczy
luschn,
Zrobiłem na to opakowanie. ale ten interfejs API daje mi błąd 401
hkg328
1
@ hkg328 musisz zakodować ciąg nazwa_użytkownika: hasło do base64, jeśli chcesz ręcznie ustawić nagłówek. coś w rodzaju import btoa z „btoa-lite”; token = btoa (nazwa użytkownika + ':' + hasło); następnie ustaw nagłówek na „Basic” + token;
krewetka
54

Powodem, dla którego kod w twoim pytaniu nie jest uwierzytelniany, jest to, że wysyłasz autoryzację w obiekcie danych, a nie w konfiguracji, która umieści ją w nagłówkach. Za tych docs Axios The prośba metoda alias na postto:

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

Dlatego, aby Twój kod działał, musisz wysłać pusty obiekt na dane:

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');
});

To samo dotyczy używania parametru auth wspomnianego przez @luschn. Poniższy kod jest równoważny, ale zamiast tego używa parametru auth (a także przekazuje pusty obiekt danych):

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
źródło
1
TO POMOGŁO, DZIĘKI
superrcoop
1
To powinna być akceptowana odpowiedź. Zaakceptowana odpowiedź to tylko kopia dokumentacji.
Sinister Beard
5

Z pewnych powodów ten prosty problem blokuje wielu programistów. Przez wiele godzin walczyłem z tą prostą rzeczą. Ten problem w wielu wymiarach:

  1. CORS (jeśli używasz frontendu i backendu na różnych domenach i portach.
  2. Konfiguracja CORS zaplecza
  3. Podstawowa konfiguracja uwierzytelniania Axios

CORS

Moja konfiguracja do programowania obejmuje aplikację vuejs webpack działającą na hoście lokalnym: 8081 i aplikację rozruchową wiosną działającą na hoście lokalnym: 8080. Więc kiedy próbuję wywołać rest API z frontendu, nie ma możliwości, żeby przeglądarka pozwoliła mi otrzymać odpowiedź z backendu sprężynowego bez odpowiednich ustawień CORS. CORS może służyć do złagodzenia ochrony skryptów międzydomenowych (XSS), które mają nowoczesne przeglądarki. Jak rozumiem, przeglądarki chronią Twoje SPA przed atakiem XSS. Oczywiście niektóre odpowiedzi na StackOverflow sugerowały dodanie wtyczki Chrome w celu wyłączenia ochrony XSS, ale to naprawdę działa, a gdyby tak było, tylko popchnęłoby nieunikniony problem na później.

Konfiguracja CORS zaplecza

Oto, jak należy skonfigurować CORS w aplikacji do rozruchu wiosennego:

Dodaj klasę CorsFilter, aby dodać odpowiednie nagłówki w odpowiedzi na żądanie klienta. Access-Control-Allow-Origin i Access-Control-Allow-Headers to najważniejsze elementy podstawowego uwierzytelniania.

    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);

    }
...
}

Dodaj klasę konfiguracji, która rozszerza Spring WebSecurityConfigurationAdapter. W tej klasie wstrzykniesz swój filtr 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());
    }
...
}

Nie musisz umieszczać niczego związanego z CORS w swoim kontrolerze.

Frontend

Teraz w interfejsie musisz utworzyć zapytanie Axios z nagłówkiem 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>

Mam nadzieję że to pomoże.

Erick Audet
źródło
noob CORS pytanie, to jest używane tylko w programowaniu, prawda?
Len Joseph
Nie, jest również i głównie w produkcji.
Erick Audet
3

Przykład (axios_example.js) przy użyciu Axios w 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);

Upewnij się, że w katalogu projektu robisz:

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

Następnie możesz przetestować interfejs REST API Node.js za pomocą przeglądarki pod adresem: http://localhost:5000/search?queryStr=xxxxxxxxx

Ref: https://github.com/axios/axios

Yuci
źródło
3

Rozwiązanie podane przez luschn i pillravi działa dobrze, chyba że w odpowiedzi otrzymasz nagłówek Strict-Transport-Security .

Dodanie withCredentials: true rozwiąże ten problem.

  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');
  });
Leonard Saers
źródło