Spring Boot 2.x(九):遇到跨域不再慌

Vi的技術部落格發表於2019-08-02

什麼是跨域

首先,我們需要了解一下一個URL是怎麼組成的:

// 協議 + 域名(子域名 + 主域名) + 埠號 + 資源地址 http: + // + www.baidu.com + :8080/

只要協議,子域名,主域名,埠號這四項組成部分中有一項不同,就可以認為是不同的域,不同的域之間互相訪問資源,就被稱之為跨域。

隨著前後端分離開發的越來越普及,會經常遇到跨域的問題,當我們在瀏覽器中看到這樣的錯誤時,就需要意識到遇到了跨域:

Spring Boot 2.x(九):遇到跨域不再慌

解決跨域的幾種方案

首先,我們使用vue-cli來快速構建一個前端專案,然後使用axios來向後臺傳送ajax請求。然後在控制檯中列印出返回資訊。這裡就不再多做贅述,後面我會單獨寫一篇文章來講一下如何使用vue-cli快速建立一個vue專案。

這裡不再講解使用jsonp的方式來解決跨域,因為jsonp方式只能通過get請求方式來傳遞引數,而且有一些不便之處。

下面的幾種方式都是通過**跨域訪問技術CORS(Cross-Origin Resource Sharing)**來解決的。具體的實現原理我們不做深入的探究,這節課的目的是解決跨域問題~

方法一:註解

在Spring Boot 中給我們提供了一個註解@CrossOrigin來實現跨域,這個註解可以實現方法級別的細粒度的跨域控制。我們可以在類或者方新增該註解,如果在類上新增該註解,該類下的所有介面都可以通過跨域訪問,如果在方法上新增註解,那麼僅僅只限於加註解的方法可以訪問。

@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController {
   @Autowired
    private UserService userService;

   @RequestMapping("/findAll")
    public Object findAll(){
        return userService.list();
    }
}
複製程式碼

現在再去測試一下:

Spring Boot 2.x(九):遇到跨域不再慌

Bingo,成功!

方法二:實現WebMvcConfigurer

這裡可以通過實現WebMvcConfigurer介面中的addCorsMappings()方法來實現跨域。

@Configuration
class CORSConfiguration implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}
複製程式碼

下面我們將剛剛加上的註解給註釋掉,看看能不能訪問到這個介面:

Spring Boot 2.x(九):遇到跨域不再慌

不出我們所料,果然還是可以的~

方法三:Filter

我們可以通過實現Fiter介面在請求中新增一些Header來解決跨域的問題:

@Component
public class CORSFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.addHeader("Access-Control-Allow-Credentials", "true");
        res.addHeader("Access-Control-Allow-Origin", "*");
        res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
        if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {
            response.getWriter().println("ok");
            return;
        }
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}
複製程式碼

不出意外的話,應該也可以在控制檯獲取到返回資訊。

Nginx配置解決跨域問題

如果我們在專案中使用了Nginx,可以在Nginx中新增以下的配置來解決跨域(原理其實和Filter類似,只不過把活兒丟給了運維?)

location / {
   add_header Access-Control-Allow-Origin *;
   add_header Access-Control-Allow-Headers X-Requested-With;
   add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;

   if ($request_method = 'OPTIONS') {
     return 204;
   }
}
複製程式碼

原創文章,才疏學淺,如有不對之處,萬望告知!


公眾號

Spring Boot 2.x(九):遇到跨域不再慌

您的推薦就是對我最大的支援!

相關文章