我作出React的网站,要求远程http API(由第三方管理)。我的网站是使用https与valide证书。
- 第三方API由URL中的一个简单GET参数“?key=XXXX”“保护”,以检查我们是否可以访问端点。
- 第三方API具有CORS
为了能够请求http远程API,我做了一个nginx反向代理。使用额外的头来允许CORS。为了更安全一点,我添加了JWT令牌验证。
一切都很好,如果标头授权载体与令牌是无效的或未设置我不能访问第三方API. nginx是阻止我。
但只要我提供了一个有效的授权头一次,任何进一步的请求将通过。令牌不再检查,即使我从不同的设备与不同的IP的请求。
如何检查我发出的每个请求的令牌
这是我的nginx配置文件
server {
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem;
location / {
default_type application/json;
return 200 '{"message": "Endpoint is required"}';
}
location ^~ /api/ {
include jwt.conf;
include headers.conf;
set $args $args&key={KEY};
proxy_pass http://www.third-party.com/api/;
}
}
这是我的jwt.conf文件,我使用的是openresty lua-nginx模块
access_by_lua_block {
local jwt = require "resty.jwt"
local jwt_obj = jwt:verify("{SECRET}", token, claim_spec)
local auth_header = ngx.var.http_Authorization
if auth_header then
_, _, token = string.find(auth_header, "Bearer%s+(.+)")
end
if token == nil then
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.header.content_type = "application/json; charset=utf-8"
ngx.say("{\"error\": \"missing JWT token or Authorization header\"}")
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
if not jwt_obj["verified"] then
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.log(ngx.WARN, jwt_obj.reason)
ngx.header.content_type = "application/json; charset=utf-8"
ngx.say("{\"error\": \"" .. jwt_obj.reason .. "\"}")
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
}
为了完整起见,我的headers.conf
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_buffers 32 16k;
proxy_busy_buffers_size 64k;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
add_header 'Access-Control-Max-Age' 1728000;
return 204;
}
# Ajouter les headers de contrôle d'accès CORS
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Authorization' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
1条答案
按热度按时间ktca8awb1#
此处:
_, _, token = string.find(auth_header, "Bearer%s+(.+)")
您将
token
声明为 * 全局 * 变量。* 强烈建议不要 * 这样做:请注意,* 强烈建议 * 使用全局Lua变量,因为这可能导致并发请求之间出现意外的争用情况。
它解释了为什么在不包含
Authorization
头的情况下,后续请求会被授权--来自初始请求的token
被"缓存"在Lua全局状态中。此外,这里:
local jwt_obj = jwt:verify("{SECRET}", token, claim_spec)
您在声明
token
变量 * 之前 * 引用了它。正确的代码如下所示: