По некоторым причинам эта простая проблема блокирует многих разработчиков. Я много часов боролся с этой простой вещью. Эта проблема как многогранная:
- CORS (если вы используете интерфейс и серверную часть на разных доменах и портах.
- Конфигурация Backend CORS
- Базовая конфигурация аутентификации Axios
CORS
Моя установка для разработки - это приложение vuejs webpack, работающее на localhost: 8081, и приложение весенней загрузки, работающее на localhost: 8080. Таким образом, при попытке вызвать rest API из внешнего интерфейса браузер не позволит мне получить ответ от весеннего внутреннего интерфейса без правильных настроек CORS. CORS можно использовать для ослабления защиты Cross Domain Script (XSS), которая есть в современных браузерах. Насколько я понимаю, браузеры защищают ваш SPA от атаки XSS. Конечно, в некоторых ответах на StackOverflow предлагалось добавить плагин chrome для отключения защиты XSS, но это действительно работает, И если бы это было так, это только подтолкнуло бы неизбежную проблему на потом.
Конфигурация Backend CORS
Вот как следует настроить CORS в приложении для весенней загрузки:
Добавьте класс CorsFilter, чтобы добавить правильные заголовки в ответ на запрос клиента. Access-Control-Allow-Origin и Access-Control-Allow-Headers - самые важные вещи, которые нужно иметь для базовой аутентификации.
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);
}
...
}
Добавьте класс конфигурации, который расширяет Spring WebSecurityConfigurationAdapter. В этом классе вы вставите свой фильтр 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());
}
...
}
Вам не нужно помещать в контроллер ничего, связанное с CORS.
Внешний интерфейс
Теперь во фронтенде вам нужно создать свой запрос axios с заголовком авторизации:
<!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>
Надеюсь это поможет.