Untuk beberapa alasan, masalah sederhana ini memblokir banyak pengembang. Saya berjuang selama berjam-jam dengan hal sederhana ini. Masalah ini banyak dimensi:
- CORS (jika Anda menggunakan frontend dan backend pada domain et port berbeda.
- Konfigurasi CORS Backend
- Konfigurasi Otentikasi Dasar Axios
CORS
Setup saya untuk pengembangan adalah dengan aplikasi webpack vuejs yang berjalan di localhost: 8081 dan aplikasi boot musim semi yang berjalan di localhost: 8080. Jadi saat mencoba memanggil rest API dari frontend, tidak mungkin browser mengizinkan saya menerima respons dari spring backend tanpa pengaturan CORS yang tepat. CORS dapat digunakan untuk melonggarkan perlindungan Cross Domain Script (XSS) yang dimiliki browser modern. Seperti yang saya pahami, browser melindungi SPA Anda dari serangan XSS. Tentu saja, beberapa jawaban di StackOverflow menyarankan untuk menambahkan plugin chrome untuk menonaktifkan perlindungan XSS tetapi ini benar-benar berfungsi DAN jika ya, hanya akan mendorong masalah yang tak terhindarkan untuk nanti.
Konfigurasi CORS backend
Inilah cara Anda mengatur CORS di aplikasi boot musim semi Anda:
Tambahkan kelas CorsFilter untuk menambahkan header yang tepat sebagai respons terhadap permintaan klien. Access-Control-Allow-Origin dan Access-Control-Allow-Headers adalah hal terpenting yang harus dimiliki untuk otentikasi dasar.
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);
}
...
}
Tambahkan kelas konfigurasi yang memperluas Spring WebSecurityConfigurationAdapter. Di kelas ini Anda akan menyuntikkan filter CORS Anda:
@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());
}
...
}
Anda tidak perlu meletakkan apapun yang berhubungan dengan CORS di controller Anda.
Paling depan
Sekarang, di frontend Anda perlu membuat kueri axios Anda dengan header Otorisasi:
<!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>
Semoga ini membantu.