Per alcuni motivi, questo semplice problema sta bloccando molti sviluppatori. Ho lottato per molte ore con questa semplice cosa. Questo problema come molte dimensioni:
- CORS (se utilizzi un frontend e un backend su domini e porte differenti.
- Configurazione CORS backend
- Configurazione dell'autenticazione di base di Axios
CORS
La mia configurazione per lo sviluppo è con un'applicazione webpack vuejs in esecuzione su localhost: 8081 e un'applicazione di avvio a molla in esecuzione su localhost: 8080. Quindi, quando provo a chiamare l'API rest dal frontend, non è possibile che il browser mi consenta di ricevere una risposta dal backend di primavera senza le impostazioni CORS appropriate. CORS può essere utilizzato per rilassare la protezione Cross Domain Script (XSS) dei browser moderni. A quanto ho capito, i browser proteggono la tua SPA dall'attacco di un XSS. Ovviamente, alcune risposte su StackOverflow suggerivano di aggiungere un plug-in Chrome per disabilitare la protezione XSS, ma funziona davvero E se lo fosse, spingerebbe solo l'inevitabile problema per dopo.
Configurazione CORS backend
Ecco come dovresti configurare CORS nella tua app di avvio primaverile:
Aggiungere una classe CorsFilter per aggiungere le intestazioni appropriate nella risposta a una richiesta del client. Le intestazioni Access-Control-Allow-Origin e Access-Control-Allow sono la cosa più importante da avere per l'autenticazione di 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);
}
...
}
Aggiungi una classe di configurazione che estende Spring WebSecurityConfigurationAdapter. In questa classe inserirai il tuo filtro 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());
}
...
}
Non è necessario inserire nulla relativo a CORS nel controller.
Fine frontale
Ora, nel frontend devi creare la tua query axios con l'intestazione di autorizzazione:
<!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>
Spero che questo ti aiuti.