Z pewnych powodów ten prosty problem blokuje wielu programistów. Przez wiele godzin walczyłem z tą prostą rzeczą. Ten problem w wielu wymiarach:
- CORS (jeśli używasz frontendu i backendu na różnych domenach i portach.
- Konfiguracja CORS zaplecza
- Podstawowa konfiguracja uwierzytelniania Axios
CORS
Moja konfiguracja do programowania obejmuje aplikację vuejs webpack działającą na hoście lokalnym: 8081 i aplikację rozruchową wiosną działającą na hoście lokalnym: 8080. Więc kiedy próbuję wywołać rest API z frontendu, nie ma możliwości, żeby przeglądarka pozwoliła mi otrzymać odpowiedź z backendu sprężynowego bez odpowiednich ustawień CORS. CORS może służyć do złagodzenia ochrony skryptów międzydomenowych (XSS), które mają nowoczesne przeglądarki. Jak rozumiem, przeglądarki chronią Twoje SPA przed atakiem XSS. Oczywiście niektóre odpowiedzi na StackOverflow sugerowały dodanie wtyczki Chrome w celu wyłączenia ochrony XSS, ale to naprawdę działa, a gdyby tak było, tylko popchnęłoby nieunikniony problem na później.
Konfiguracja CORS zaplecza
Oto, jak należy skonfigurować CORS w aplikacji do rozruchu wiosennego:
Dodaj klasę CorsFilter, aby dodać odpowiednie nagłówki w odpowiedzi na żądanie klienta. Access-Control-Allow-Origin i Access-Control-Allow-Headers to najważniejsze elementy podstawowego uwierzytelniania.
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);
}
...
}
Dodaj klasę konfiguracji, która rozszerza Spring WebSecurityConfigurationAdapter. W tej klasie wstrzykniesz swój filtr 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());
}
...
}
Nie musisz umieszczać niczego związanego z CORS w swoim kontrolerze.
Frontend
Teraz w interfejsie musisz utworzyć zapytanie Axios z nagłówkiem 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>
Mam nadzieję że to pomoże.