Por alguns motivos, esse problema simples está bloqueando muitos desenvolvedores. Lutei por muitas horas com essa coisa simples. Este problema tem tantas dimensões:
- CORS (se você estiver usando um front-end e back-end em diferentes domínios e portas.
- Configuração de Backend CORS
- Configuração de autenticação básica do Axios
CORS
Minha configuração para desenvolvimento é com um aplicativo vuejs webpack rodando em localhost: 8081 e um aplicativo Spring Boot rodando em localhost: 8080. Portanto, ao tentar chamar a API rest do front-end, não há como o navegador me deixar receber uma resposta do back-end do Spring sem as configurações CORS adequadas. O CORS pode ser usado para relaxar a proteção Cross Domain Script (XSS) que os navegadores modernos possuem. Pelo que entendi, os navegadores estão protegendo seu SPA de ser um ataque de um XSS. Claro, algumas respostas no StackOverflow sugeriram adicionar um plug-in chrome para desabilitar a proteção XSS, mas isso realmente funciona E se fosse, apenas empurraria o problema inevitável para mais tarde.
Configuração de back-end CORS
Veja como você deve configurar o CORS em seu aplicativo Spring Boot:
Adicione uma classe CorsFilter para adicionar cabeçalhos adequados na resposta a uma solicitação do cliente. Access-Control-Allow-Origin e Access-Control-Allow-Headers são os itens mais importantes para autenticação 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);
}
...
}
Adicione uma classe de configuração que estende Spring WebSecurityConfigurationAdapter. Nesta aula, você injetará seu 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());
}
...
}
Você não precisa colocar nada relacionado ao CORS em seu controlador.
A parte dianteira
Agora, no front-end, você precisa criar sua consulta axios com o cabeçalho 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>
Espero que isto ajude.