Cross-Origin Resource Sharing 跨來源資源共享

近期在部屬專案時因為測試都在地端或本機,二階段測試上雲並掛上https網域tls憑證後,不斷地爆各種cros 錯誤,所以來了解一下

後端server 未設定cros

如果後端伺服器沒有設定允許你的網域訪問,則會出現 CORS 錯誤

1
No Access-Control-Allow-Origin

springboot

我這邊的後端server 是採用springboot, 因此可以在security chain中加入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout();
}

@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://example.com")); // 允許的網域
configuration.setAllowedMethods(Arrays.asList("GET", "POST")); // 允許的 HTTP 方法
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}

nodejs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const express = require('express');
const cors = require('cors');

const app = express();

var corsOptions = {
origin: 'https://example.com', // 允許的網域
methods: ['GET', 'POST'], // 允許的 HTTP 方法
credentials: true, // 允許帶有 cookies 的請求
allowedHeaders: ['Authorization', 'Cache-Control', 'Content-Type'] // 允許的 headers
};

app.use(cors(corsOptions));

// 其他路由和中間件...

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

nginx

cros.config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
server {
listen 80;

location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://example.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' 'https://example.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' 'https://example.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
}

指令

1
2
include /path/to/your/cors.conf;
docker restart <container-id>

以上三種方法都會讓只有 https://example.com 這個網域可以直接訪問,另外因為只設定GET POST 如果使用 PUT DELETE 也會被擋


Cross-Origin Resource Sharing 跨來源資源共享
https://shengshengyang.github.io/2024/03/25/cros/
作者
Dean Yang
發布於
2024年3月25日
許可協議