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 Einstellen von Basic Auth. Wenn ich diese Felder nicht ausfülle, wird auch 401 zurückgegeben. Ist dies der Fall, ist die Anforderung erfolgreich.
Irgendwelche Ideen, was ich falsch mache?
Hier ist ein Teil der Dokumentation der API, wie Sie dies implementieren können:
Dieser Dienst verwendet Basisauthentifizierungsinformationen im Header, um eine Benutzersitzung einzurichten. Anmeldeinformationen werden gegen den Server geprüft. Mit diesem Webdienst wird eine Sitzung mit den übergebenen Benutzeranmeldeinformationen erstellt und eine JSESSIONID zurückgegeben. Diese JSESSIONID kann in den nachfolgenden Anforderungen für Webdienstaufrufe verwendet werden. *
Es gibt einen "Auth" -Parameter für Basic Auth:
auth: {
username: 'janedoe',
password: 's00pers3cret'
}
Quelle/Dokumente: https://github.com/mzabriskie/axios
Der Grund, warum sich der Code in Ihrer Frage nicht authentifiziert, liegt darin, dass Sie die Authentifizierung im Datenobjekt senden, nicht in der Konfiguration, die ihn in die Kopfzeilen setzt. Gemäß der axios docs lautet der Alias [] der request-Methode für post
:
axios.post (url [ data [ config]])
Damit Ihr Code funktioniert, müssen Sie 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 angegebenen auth-Parameters. Der folgende Code ist gleichwertig, 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');
});
Aus einigen Gründen blockiert dieses einfache Problem viele Entwickler. Ich hatte viele Stunden mit dieser einfachen Sache zu kämpfen. Dieses Problem so viele Dimensionen:
CORS
Mein Setup für die Entwicklung besteht aus einer vuejs-Webpack-Anwendung, die auf localhost: 8081 ausgeführt wird, und einer Spring-Boot-Anwendung, die auf localhost: 8080 ausgeführt wird. Wenn ich also versuche, die Rest-API vom Frontend aus aufzurufen, kann der Browser auf keinen Fall zulassen, dass ich vom Spring-Backend eine Antwort erhalte, ohne die richtigen CORS-Einstellungen vorzunehmen. CORS kann verwendet werden, um den XSS-Schutz (Cross Domain Script) moderner Browser zu lockern. Soweit ich weiß, schützen Browser Ihr SPA vor Angriffen durch ein XSS. Einige Antworten auf StackOverflow schlugen natürlich vor, ein chrome) - Plugin hinzuzufügen, um den XSS-Schutz zu deaktivieren, aber das funktioniert wirklich, UND wenn ja, würde es das unvermeidliche Problem nur für später verschieben.
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.
Frontend
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.
Die Lösung von luschn und pillravi funktioniert einwandfrei, es sei denn, Sie erhalten in der Antwort den Header Strict-Transport-Security .
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');
});
Ein Beispiel (axios_example.js), das Axios in Node.js verwendet:
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 mithilfe Ihres Browsers testen: http://localhost:5000/search?queryStr=xxxxxxxxx