SpringBoot 實現跨網域請求 CORS
一、前言
因為安全性的關係,瀏覽器預設都會限制跨網域請求。如果今天有這方面的需求,就需要開放一個對應的API連線,而CORS就是一個瀏覽器要做跨網域請求的規範
二、實作步驟
1.先建立一個SpringBoot maven專案,在pom.xml加入相關的依賴項目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.beef</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.在SpringBoot中,有四種方法可以實作CORS方式
一.CorsFilter(全域跨網域)
二.覆寫WebMvcConfigurer
三.使用Annotation(@CrossOrigin)
四.手動設定response header
3-1.CorsFilter(全域跨網域)
在環境配置設置一個JavaConfig Bean
package com.beef.demo.configurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//允許跨網域請求的來源
config.addAllowedOrigin("/*");
//允許跨域攜帶cookie資訊,預設跨網域請求是不攜帶cookie資訊的。
config.setAllowCredentials(true);
//允許使用那些請求方式
config.addAllowedMethod("/*");
//config.setAllowedMethods(Arrays.asList("GET", "PUT", "POST","DELETE"));
//config.addAllowedMethod(HttpMethod.POST);
//允許哪些Header
config.addAllowedHeader("/*");
//config.addAllowedHeader("x-firebase-auth");
//可獲取哪些Header(因為跨網域預設不能取得全部Header資訊)
config.addExposedHeader("/*");
//config.addExposedHeader("Content-Type");
//config.addExposedHeader( "X-Requested-With");
//config.addExposedHeader("accept");
//config.addExposedHeader("Origin");
//config.addExposedHeader( "Access-Control-Request-Method");
//config.addExposedHeader("Access-Control-Request-Headers");
//映射路徑
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//return一個的CorsFilter.
return new CorsFilter(configSource);
}
}
3-2.覆寫WebMvcConfigurer
@Configuration
public class GlobalCorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
//映射路徑
registry.addMapping("/**")
//允許跨網域請求的來源
.allowedOrigins("/*")
//允許跨域攜帶cookie資訊,預設跨網域請求是不攜帶cookie資訊的。
.allowCredentials(true)
//允許使用那些請求方式
.allowedMethods("GET", "POST", "PUT", "DELETE")
//允許哪些Header
.allowedHeaders("/*")
//可獲取哪些Header(因為跨網域預設不能取得全部Header資訊)
.exposedHeaders("Header1", "Header2");
}
};
}
}
3-3.使用Annotation(@CrossOrigin )
在MVC Controller中,可以在方法上(@RequestMapping)使用註解 @CrossOrigin
@RestController
public class DemoApplication {
@RequestMapping("/hello")
@CrossOrigin("http://localhost:8080")
public String index() {
return "Hello World;
}
}
也可以在Controller(@Controller)上使用註解 @CrossOrigin
@Controller
@CrossOrigin(value = "http://localhost:8080")
public class CorsController {
@RequestMapping("/hello")
@ResponseBody
public String index( ){
return "Hello World";
}
}
3-4手動設定response header
@Controller
public class CorsController {
@RequestMapping("/hello")
@ResponseBody
public String index(HttpServletResponse response){
response.addHeader("Access-Control-Allow-Origin", "http://localhost:8080");
return "Hello World";
}
}
4.測試
4-1寫一個簡單Ajax來測試跨網域請求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Page Index</title>
</head>
<body>
<h2>CORS測試</h2>
<p id="info"></p>
</body>
<script src="https://code.jquery.com/jquery-3.4.1.js"></script>
<script>
$.ajax({
url: 'http://localhost:8080/hello',
type: "POST",
success: function (data) {
$("#info").html("跨網域請求成功:"+data);
},
error: function (data) {
$("#info").html("跨網域請求失敗!!");
}
})
</script>
</html>
4-2另開一個新的springboot web專案,將這個Html放入static資料夾
4-3.接著把這個專案的Tomcat server port改成8090,方便我們同時啟動兩邊的server做測試
@SpringBootApplication
public class DemoApplication {
@Bean
public TomcatServletWebServerFactory tomcat() {
TomcatServletWebServerFactory tomcatFactory = new TomcatServletWebServerFactory();
tomcatFactory.setPort(8090); //port 8090
return tomcatFactory;
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
4-4已Annotation方法為例,先把CorssOrigin註解掉並啟動server,然後在另一邊執行剛寫好的跨網域請求Ajax
@RestController
public class CorsController {
@RequestMapping("/hello")
// @CrossOrigin("http://localhost:8090")
public String index() {
return "Hello World:8090";
}
}
4-5.在console可以看到請求被瀏覽器拒絕
4-6.再把註解拿掉後重啟server後重整網頁,就可以看到CORS執行成功
參考來源:https://howtodoinjava.com/spring5/webmvc/spring-mvc-cors-configuration/