Por algunas razones, este simple problema está bloqueando a muchos desarrolladores. Luché durante muchas horas con esta simple cosa. Este problema tantas dimensiones:
- CORS (si está utilizando un frontend y un backend en diferentes dominios y puertos.
- Configuración de CORS backend
- Configuración de autenticación básica de Axios
CORS
Mi configuración para el desarrollo es con una aplicación de paquete web vuejs que se ejecuta en localhost: 8081 y una aplicación de arranque de primavera que se ejecuta en localhost: 8080. Entonces, cuando intento llamar a la API de descanso desde el frontend, no hay forma de que el navegador me permita recibir una respuesta del backend de primavera sin la configuración CORS adecuada. CORS se puede utilizar para relajar la protección Cross Domain Script (XSS) que tienen los navegadores modernos. Según tengo entendido, los navegadores protegen su SPA de un ataque de un XSS. Por supuesto, algunas respuestas en StackOverflow sugirieron agregar un complemento de Chrome para deshabilitar la protección XSS, pero esto realmente funciona Y si lo fuera, solo empujaría el problema inevitable para más adelante.
Configuración de backend CORS
Así es como debe configurar CORS en su aplicación de arranque de primavera:
Agregue una clase CorsFilter para agregar encabezados adecuados en la respuesta a una solicitud de cliente. Access-Control-Allow-Origin y Access-Control-Allow-Headers son lo más importante para la autenticación básica.
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);
}
...
}
Agregue una clase de configuración que amplíe Spring WebSecurityConfigurationAdapter. En esta clase inyectarás tu 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());
}
...
}
No tiene que poner nada relacionado con CORS en su controlador.
Interfaz
Ahora, en la interfaz, debe crear su consulta axios con el encabezado Autorización:
<!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>
Espero que esto ayude.