Cara mengirim Basic Auth dengan axios

110

Saya mencoba menerapkan kode berikut, tetapi ada sesuatu yang tidak berfungsi. Ini kodenya:

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

Ini mengembalikan kesalahan 401. Saat saya melakukannya dengan Postman, ada opsi untuk menyetel Basic Auth; jika saya tidak mengisi kolom tersebut, ia juga mengembalikan 401, tetapi jika saya melakukannya, permintaan berhasil.

Ada ide apa yang saya lakukan salah?

Berikut adalah bagian dari dokumen API tentang cara mengimplementasikannya:

Layanan ini menggunakan informasi otentikasi dasar di header untuk membuat sesi pengguna. Kredensial divalidasi terhadap Server. Menggunakan layanan web ini akan membuat sesi dengan kredensial pengguna yang diteruskan dan mengembalikan JSESSIONID. JSESSIONID ini dapat digunakan dalam permintaan berikutnya untuk melakukan panggilan layanan web. *

Emmanuel
sumber

Jawaban:

157

Ada parameter "auth" untuk Basic Auth:

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

Sumber / Dokumen: https://github.com/mzabriskie/axios

Contoh:

await axios.post(session_url, {}, {
  auth: {
    username: uname,
    password: pass
  }
});
luschn
sumber
4
halo, bagaimana saya bisa mengaturnya ke semua panggilan axios? Saya perlu menambahkan otentikasi Dasar ke semua panggilan ajax. axios.defaults.auth = {username: 'dd', password: '##'} ini tidak berfungsi untuk saya.
hkg328
Btw, Anda juga dapat menulis pembungkus di sekitar aksios untuk hal
luschn
Saya membuat pembungkus untuk itu. tetapi api itu memberi saya kesalahan 401
hkg328
1
@ hkg328 Anda perlu menyandikan string username: password ke base64 jika Anda ingin menyetel header secara manual. sesuatu seperti import btoa dari 'btoa-lite'; token = btoa (nama pengguna + ':' + kata sandi); lalu setel header ke 'Basic' + token;
shrumm
54

Alasan kode dalam pertanyaan Anda tidak diautentikasi adalah karena Anda mengirimkan autentikasi di objek data, bukan di konfigurasi, yang akan meletakkannya di header. Per docs axio , yang permintaan metode alias untuk postadalah:

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

Oleh karena itu, agar kode Anda berfungsi, Anda perlu mengirim objek kosong untuk data:

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

Hal yang sama juga berlaku untuk menggunakan parameter auth yang disebutkan oleh @luschn. Kode berikut ini setara, tetapi menggunakan parameter auth sebagai gantinya (dan juga meneruskan objek data kosong):

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
sumber
1
INI MEMBANTU, TERIMA KASIH
superrcoop
1
Ini harus menjadi jawaban yang diterima. Jawaban yang diterima hanyalah duplikat dari dokumentasi.
Sinister Beard
5

Untuk beberapa alasan, masalah sederhana ini memblokir banyak pengembang. Saya berjuang selama berjam-jam dengan hal sederhana ini. Masalah ini banyak dimensi:

  1. CORS (jika Anda menggunakan frontend dan backend pada domain et port berbeda.
  2. Konfigurasi CORS Backend
  3. Konfigurasi Otentikasi Dasar Axios

CORS

Setup saya untuk pengembangan adalah dengan aplikasi webpack vuejs yang berjalan di localhost: 8081 dan aplikasi boot musim semi yang berjalan di localhost: 8080. Jadi saat mencoba memanggil rest API dari frontend, tidak mungkin browser mengizinkan saya menerima respons dari spring backend tanpa pengaturan CORS yang tepat. CORS dapat digunakan untuk melonggarkan perlindungan Cross Domain Script (XSS) yang dimiliki browser modern. Seperti yang saya pahami, browser melindungi SPA Anda dari serangan XSS. Tentu saja, beberapa jawaban di StackOverflow menyarankan untuk menambahkan plugin chrome untuk menonaktifkan perlindungan XSS tetapi ini benar-benar berfungsi DAN jika ya, hanya akan mendorong masalah yang tak terhindarkan untuk nanti.

Konfigurasi CORS backend

Inilah cara Anda mengatur CORS di aplikasi boot musim semi Anda:

Tambahkan kelas CorsFilter untuk menambahkan header yang tepat sebagai respons terhadap permintaan klien. Access-Control-Allow-Origin dan Access-Control-Allow-Headers adalah hal terpenting yang harus dimiliki untuk otentikasi dasar.

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

    }
...
}

Tambahkan kelas konfigurasi yang memperluas Spring WebSecurityConfigurationAdapter. Di kelas ini Anda akan menyuntikkan filter CORS Anda:

@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());
    }
...
}

Anda tidak perlu meletakkan apapun yang berhubungan dengan CORS di controller Anda.

Paling depan

Sekarang, di frontend Anda perlu membuat kueri axios Anda dengan header Otorisasi:

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

Semoga ini membantu.

Erick Audet
sumber
noob CORS pertanyaan, ini hanya digunakan dalam pengembangan, bukan?
Len Joseph
Tidak, itu juga dan sebagian besar dalam produksi.
Erick Audet
3

Contoh (axios_example.js) menggunakan Axios di 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);

Pastikan di direktori proyek Anda, Anda melakukan:

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

Anda kemudian dapat menguji Node.js REST API menggunakan browser Anda di: http://localhost:5000/search?queryStr=xxxxxxxxx

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

Yuci
sumber
3

Solusi yang diberikan oleh luschn dan pillravi berfungsi dengan baik kecuali Anda menerima tajuk Strict-Transport-Security sebagai tanggapan.

Menambahkan withCredentials: true akan menyelesaikan masalah itu.

  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
sumber
1

Jika Anda mencoba melakukan autentikasi dasar, Anda dapat mencoba ini:

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}`
},
})

Ini berhasil untuk saya. Semoga membantu

Fotie M. Constant
sumber