So senden Sie Basic Auth mit Axios

106

Ich versuche, den folgenden Code zu implementieren, aber etwas funktioniert nicht. Hier ist der Code:

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

Es wird ein 401-Fehler zurückgegeben. Wenn ich es mit Postman mache, gibt es eine Option zum Festlegen der Basisauthentifizierung. Wenn ich diese Felder nicht ausfülle, wird auch 401 zurückgegeben. Wenn ich dies jedoch tue, ist die Anforderung erfolgreich.

Irgendwelche Ideen, was ich falsch mache?

Hier ist ein Teil der Dokumente der API, wie dies implementiert wird:

Dieser Dienst verwendet grundlegende Authentifizierungsinformationen im Header, um eine Benutzersitzung einzurichten. Anmeldeinformationen werden gegen den Server validiert. Wenn Sie diesen Webdienst verwenden, wird eine Sitzung mit den übergebenen Benutzeranmeldeinformationen erstellt und eine JSESSIONID zurückgegeben. Diese JSESSIONID kann in den nachfolgenden Anforderungen zum Tätigen von Webdienstaufrufen verwendet werden. *

Emmanuel
quelle

Antworten:

150

Es gibt einen "auth" -Parameter für Basic Auth:

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

Quelle / Dokumente: https://github.com/mzabriskie/axios

Beispiel:

await axios.post(session_url, {}, {
  auth: {
    username: uname,
    password: pass
  }
});
luschn
quelle
4
Hallo, wie kann ich das in alle Axios-Anrufe einfügen? Ich muss Basic Authentifizierung zu allen Ajax-Aufrufen hinzufügen. axios.defaults.auth = {Benutzername: 'dd', Passwort: '##'} Dies funktioniert bei mir nicht.
hkg328
Übrigens können Sie auch einen Wrapper um Axios für diese Art von Dingen schreiben
luschn
Ich habe Wrapper dafür gemacht. aber diese API gibt mir 401 Fehler
hkg328
1
@ hkg328 Sie müssen den String-Benutzernamen: password in base64 codieren, wenn Sie den Header manuell festlegen möchten. so etwas wie Btoa aus 'Btoa-Lite' importieren; token = btoa (Benutzername + ':' + Passwort); Setzen Sie dann den Header auf 'Basic' + Token.
Shrumm
54

Der Grund, warum sich der Code in Ihrer Frage nicht authentifiziert, liegt darin, dass Sie die Authentifizierung im Datenobjekt und nicht in der Konfiguration senden, wodurch sie in die Header eingefügt wird. Gemäß den Axios-Dokumenten lautet der Alias für die Anforderungsmethodepost :

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

Damit Ihr Code funktioniert, müssen Sie daher ein leeres Objekt für Daten senden:

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

Gleiches gilt für die Verwendung des von @luschn genannten auth-Parameters. Der folgende Code ist äquivalent, verwendet jedoch stattdessen den Parameter auth (und übergibt auch ein leeres Datenobjekt):

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
quelle
1
Dies half, danke
Superrcoop
1
Dies sollte die akzeptierte Antwort sein. Die akzeptierte Antwort ist nur ein Duplikat der Dokumentation.
Unheimlicher Bart
5

Aus bestimmten Gründen blockiert dieses einfache Problem viele Entwickler. Ich hatte viele Stunden mit dieser einfachen Sache zu kämpfen. Dieses Problem so viele Dimensionen:

  1. CORS (wenn Sie ein Frontend und ein Backend für verschiedene Domänen und Ports verwenden.
  2. Backend-CORS-Konfiguration
  3. Grundlegende Authentifizierungskonfiguration von Axios

CORS

Mein Setup für die Entwicklung ist mit einer vuejs-Webpack-Anwendung, die auf localhost: 8081 ausgeführt wird, und einer Spring-Boot-Anwendung, die auf localhost: 8080 ausgeführt wird. Wenn Sie also versuchen, die Rest-API vom Frontend aus aufzurufen, kann der Browser ohne die richtigen CORS-Einstellungen keine Antwort vom Spring-Backend erhalten. Mit CORS kann der XSS-Schutz (Cross Domain Script) moderner Browser gelockert werden. Soweit ich weiß, schützen Browser Ihr SPA vor einem Angriff durch ein XSS. Natürlich schlugen einige Antworten auf StackOverflow vor, ein Chrome-Plugin hinzuzufügen, um den XSS-Schutz zu deaktivieren, aber dies funktioniert wirklich UND wenn dies der Fall wäre, würde das unvermeidliche Problem nur für später verschoben.

Backend-CORS-Konfiguration

So sollten Sie CORS in Ihrer Spring Boot-App einrichten:

Fügen Sie eine CorsFilter-Klasse hinzu, um der Antwort auf eine Clientanforderung die richtigen Header hinzuzufügen. Access-Control-Allow-Origin und Access-Control-Allow-Header sind das Wichtigste für die Basisauthentifizierung.

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

    }
...
}

Fügen Sie eine Konfigurationsklasse hinzu, die Spring WebSecurityConfigurationAdapter erweitert. In dieser Klasse injizieren Sie Ihren CORS-Filter:

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

Sie müssen nichts in Bezug auf CORS in Ihren Controller einfügen.

Vorderes Ende

Jetzt müssen Sie im Frontend Ihre Axios-Abfrage mit dem Authorization-Header erstellen:

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

Hoffe das hilft.

Erick Audet
quelle
noob CORS frage, das wird nur in der entwicklung verwendet, oder?
Len Joseph
Nein, es ist auch und meistens in Produktion.
Erick Audet
3

Ein Beispiel (axios_example.js) mit Axios in 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);

Stellen Sie sicher, dass Sie in Ihrem Projektverzeichnis Folgendes tun:

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

Anschließend können Sie die Node.js-REST-API mit Ihrem Browser unter folgender Adresse testen: http://localhost:5000/search?queryStr=xxxxxxxxx

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

Yuci
quelle
3

Die von luschn und pillravi gegebene Lösung funktioniert einwandfrei, es sei denn, Sie erhalten in der Antwort einen Strict-Transport-Security- Header.

Durch Hinzufügen von withCredentials: true wird dieses Problem behoben .

  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
quelle