SpringBoot Vue Axios 實現前後端分離的跨域訪問(CORS-Cross-Origin Resource Sharing)
在 使用 Eclipse 快速建立 Spring Starter Project 與相關的文章裡,可以見識到 Spring 在後端 Java 平台的快速開發;前端 在 Node JS 使用 vue-cli 3 快速開發網頁與佈署到 github-pages ,可以使用 vue-cli 3 與 Vue Router 去建立單一網頁,只需利用 Axios 的 ajax 技術向後端取得資料, 而 Vue Router 不需作跳轉頁面。要達成這樣前後端分離的要求,需要在 Spring boot 配置跨域訪問(CORS-Cross-Origin Resource Sharing)
- 建立 CorsFilter
因為跨域需設定 Access-Control-Allow-Credentials
為 true , 所以設定 Access-Control-Allow-Origin
允許來自那個網站發的請求時,不可以設為 ‘*’
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; 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; // addAllowedOrigin 不能設定為* 因為與 allowCredential 衝突 response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080"); response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS"); response.setHeader("Access-Control-Allow-Headers", "*"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Max-Age", "180"); filterChain.doFilter(servletRequest, servletResponse); } }
- 設定 WebSecurityConfigurerAdapter
code: 38-42 行建立 Bean: corsFilter ,並放在 code: 11 行加入自定義的 CorsFilter,因為還沒有寫認證程式,所以在 code: 35 行中對 "/auth/**"
的請求都允許。認證方式請參閱:Spring Boot 與 Vue + Axios 跨域訪問(CORS)並使用 JWT 解決 302(OPTIONS) 問題
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity //adds your custom CorsFilter .addFilterBefore(corsFilter(), (Class<? extends Filter>) SessionManagementFilter.class) // CSRF Token .csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and() .authorizeRequests() .anyRequest().authenticated().and() .formLogin() .loginPage("/login") // 認證頁面指向頁頁 .failureHandler(appsAuthenticationFailureHandler) .defaultSuccessUrl("/auth/home") .permitAll() .successHandler(appsAuthenticationSuccessHandler) .and() .logout() .logoutSuccessHandler(appsLogoutSuccessHandler) .and() .sessionManagement() .maximumSessions(1).sessionRegistry(sessionRegistry()); } @Override public void configure(WebSecurity web) throws Exception { // for axios CORS web.ignoring().antMatchers("/auth/**"); } @Bean CorsFilter corsFilter() { CorsFilter filter = new CorsFilter(); return filter; } }
- 設定 axios 的初始值
在 code: 13 行設定要向那個網域發出請求
import Vue from 'vue' import axios from 'axios' import VueAxios from 'vue-axios' Vue.use(VueAxios, axios) if (process.env.NODE_ENV === 'production'){ const CSRF_TOKEN = document.cookie.match(new RegExp(`XSRF-TOKEN=([^;]+)`)) == null ? "" : document.cookie.match(new RegExp(`XSRF-TOKEN=([^;]+)`))[1]; axios.defaults.headers = { "X-XSRF-TOKEN": CSRF_TOKEN, "X-REQUEST-TYPE":"axios"}; axios.defaults.timeout = 5000; } else { //axios.defaults.withCredentials = true axios.defaults.baseURL = "https://im.your-domain-name.com/"; // 域名 }
- 跨域請求(CORS-Cross-Origin Resource Sharing)
在 code: 26 行 axios 向 spring boot 發出 request ,利用 Bootstrap-vue 的 Table 來顯示。 因為 axios 與 Vue 有整合所以可以用 self.$http.post
,當然也可以直接使用 this.axios.post
。
<template> <div class="about"> <h1>This is an about page for axios request to spring boot</h1> <div lass="col-6"> <b-card class="text-center"> <b-table striped hover :items="roleList"></b-table> </b-card> </div > </div> </template> <script> export default { data() { return { roleList: [], }; }, mounted() { // 取得初始資料 let self = this; self.$http.post('/auth/security/authority/roles/list').then(response=> { self.roleList = response.data.roles;}) }, } </script>
- 觀察請求的表頭 ( Request Headers )
可以查到 Host: 是指向另一個網域
- 觀察回應的表頭 ( Response Headers )
可以查到 Access-Control-Allow-Origin
是來自 http://localhost:8080
參考:
你必須 登入 才能發表評論。