Tauri+Better Auth的跨域问题
编辑问题说明
如果是普通网页中的Better Auth那只需要前后端部署在同一域名下即可, 例如使用nginx部署前端+反向代理后端; 如果是SSR那本身就是全栈不存在跨域问题, 如果是原生应用则没有CORS跨域问题, 只需要考虑cookie兼容即可。 只有Tauri这种环境下会比较麻烦, 它无法像Electron一样轻易的关闭跨域校验, 所以一般从服务端下手。
允许跨域
如果后端直接暴露端点, 那么应该在应用层解决跨域问题, 手动添加Access-Control-Allow-*一系列响应头。例如搜索Express允许跨域、Fastify允许跨域关键字, 当然还一些一点需要注意, 建议看完全文。
或者在一般情况下为了复用443端口会在套一层Nginx, 在这种情况下就应该在Nginx中配置跨域。
OpenResty 配置
access_by_lua_block {
local allowed_origins = {
["http://tauri.localhost"] = true,
["http://localhost:14200"] = true
}
local origin = ngx.var.http_origin
if origin and allowed_origins[origin] then
ngx.header["Access-Control-Allow-Origin"] = origin
ngx.header["Access-Control-Allow-Credentials"] = "true"
ngx.header["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS, PUT, DELETE"
ngx.header["Access-Control-Allow-Headers"] = "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"
ngx.header["Access-Control-Max-Age"] = 1728000
end
if ngx.req.get_method() == "OPTIONS" and origin and allowed_origins[origin] then
ngx.exit(ngx.HTTP_NO_CONTENT)
end
}
不过由于一些面板(例如1panel)的WAF和网站监控功能依赖于access_by_lua_file, 而access_by_lua_block与access_by_lua_file是冲突,两者都存在时只会生效其中一项, 因此这种情况需要使用Nginx配置
Nginx 配置
在server外部添加map
# 当请求来源在白名单内时,$cors_origin 的值为来源地址,否则为空字符串
map $http_origin $cors_origin {
default "";
"http://tauri.localhost" $http_origin;
"http://localhost:14200" $http_origin;
}
# 当请求来源在白名单内时,$cors_creds 的值为 "true",否则为空字符串
map $http_origin $cors_creds {
default "";
"http://tauri.localhost" "true";
"http://localhost:14200" "true";
}
在location内添加配置
set $cors_request "";
if ($request_method = 'OPTIONS') {
set $cors_request "${cors_request}O";
}
if ($cors_origin != "") {
set $cors_request "${cors_request}V";
}
if ($cors_request = "OV") {
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
add_header 'Access-Control-Max-Age' 1728000 always;
return 204;
}
if ($cors_request = "O") {
return 403;
}
if ($cors_request ~ "V") {
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Access-Control-Allow-Credentials' "$cors_creds" always;
}
总结下来可能是这样:
# 当请求来源在白名单内时,$cors_origin 的值为来源地址,否则为空字符串
map $http_origin $cors_origin {
default "";
"http://tauri.localhost" $http_origin;
"http://localhost:14200" $http_origin;
}
# 当请求来源在白名单内时,$cors_creds 的值为 "true",否则为空字符串
map $http_origin $cors_creds {
default "";
"http://tauri.localhost" "true";
"http://localhost:14200" "true";
}
server {
listen 80 ;
server_name example.com;
location ^~ / {
set $cors_request "";
if ($request_method = 'OPTIONS') {
set $cors_request "${cors_request}O";
}
if ($cors_origin != "") {
set $cors_request "${cors_request}V";
}
if ($cors_request = "OV") {
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
add_header 'Access-Control-Max-Age' 1728000 always;
return 204;
}
if ($cors_request = "O") {
return 403;
}
if ($cors_request ~ "V") {
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Access-Control-Allow-Credentials' "$cors_creds" always;
}
proxy_pass http://127.0.0.1:8080;
}
}
因为nginx不支持嵌套if, 所以看起来会有OV这样的奇怪判断逻辑。
跨域配置注意事项
上述Access-Control-Allow-Origin不能直接设置为*, 因为在Access-Control-Allow-Credentials为true的情况下浏览器为了安全要求(防止CSRF攻击)Access-Control-Allow-Origin必须设置为具体值。
这里设置的http://tauri.localhost和http://localhost:14200是Tauri在生产和开发环境下的Origin
跨域配置总结
Access-Control-Allow-Origin是允许浏览器发起跨域请求
Access-Control-Allow-Credentials是允许浏览器发起跨域请求时携带cookie
allowed_origins保证了只有tauri环境下才允许跨域
Better Auth配置
trustedorigins配置
在Better Auth中还有一个 trustedorigins配置, 该配置也是为了防止CSRF攻击。
上面的OpenResty配置作用在浏览器层面, 下述Better Auth配置作用在应用层层面, 因此这里也要进行配置, 否则调用Better Auth接口时会报403:
{
trustedOrigins: [
'http://localhost:14200',
'http://tauri.localhost',
],
}
samesite配置
Better Auth默认情况下cookie设置的 samesite 为Lax, 在该配置也是在防止CSRF攻击, 该配置下Tauri中发起的请求不会携带Cookie, 所以还需要配置:
{
advanced: {
defaultCookieAttributes: {
sameSite: 'none',
secure: true,
partitioned: true,
},
},
}
合并后配置如下:
export const auth = betterAuth({
trustedOrigins: [
'http://localhost:14200',
'http://tauri.localhost',
],
advanced: {
defaultCookieAttributes: {
sameSite: 'none',
secure: true,
partitioned: true,
},
},
})
总结
首先在OpenResty中配置服务器在Tauri环境下允许跨域请求, 请求时允许发送Cookie, 但是是否真的能够自动携带Cookie发起请求还受制于samesite配置, 最后应用层也会校验Origin, 因此还需要配置trustedorigins。
- 0
- 0
-
分享