Pour certaines raisons, ce simple problème bloque de nombreux développeurs. J'ai lutté pendant de nombreuses heures avec cette chose simple. Ce problème autant de dimensions:
- CORS (si vous utilisez un frontend et un backend sur différents domaines et ports.
- Configuration CORS du backend
- Configuration de l'authentification de base d'Axios
CORS
Ma configuration pour le développement est avec une application webpack vuejs s'exécutant sur localhost: 8081 et une application de démarrage de printemps s'exécutant sur localhost: 8080. Ainsi, lorsque vous essayez d'appeler l'API rest depuis le frontend, il n'y a aucun moyen que le navigateur me permette de recevoir une réponse du backend Spring sans les paramètres CORS appropriés. CORS peut être utilisé pour assouplir la protection XSS (Cross Domain Script) offerte par les navigateurs modernes. Si je comprends bien, les navigateurs protègent votre SPA contre une attaque par un XSS. Bien sûr, certaines réponses sur StackOverflow suggéraient d'ajouter un plugin chrome pour désactiver la protection XSS, mais cela fonctionne vraiment ET si c'était le cas, cela ne ferait que pousser l'inévitable problème pour plus tard.
Configuration du backend CORS
Voici comment configurer CORS dans votre application Spring Boot:
Ajoutez une classe CorsFilter pour ajouter les en-têtes appropriés dans la réponse à une demande client. Access-Control-Allow-Origin et Access-Control-Allow-Headers sont la chose la plus importante à avoir pour l'authentification de base.
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);
}
...
}
Ajoutez une classe de configuration qui étend Spring WebSecurityConfigurationAdapter. Dans cette classe, vous injecterez votre filtre 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());
}
...
}
Vous n'avez rien à mettre en rapport avec CORS dans votre contrôleur.
L'extrémité avant
Maintenant, dans le frontend, vous devez créer votre requête axios avec l'en-tête 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>
J'espère que cela t'aides.