如何在Nginx中基于认证响应头创建map实现用户有效性校验?
Got it, let's solve this Nginx user validation problem you're dealing with. The core issue here is that map has to live in the http block, but you want to use the $auth_resp_x_auth_user variable (set in your server block) to check if a user is valid. Here are two solid solutions:
1. Use a map in the http block (native Nginx, no extra modules)
Even though map is restricted to the http block, it works dynamically with variables that are set later in the request lifecycle (like your $auth_resp_x_auth_user from auth_request_set). Nginx only evaluates the map when you reference the resulting variable, so it'll pick up the value set in your server block just fine.
Here's how to structure your config:
http { # Your existing http-level config (like include mime.types; etc.) # Define the map here - default to invalid (0), list valid users as 1 map $auth_resp_x_auth_user $is_valid_user { default 0; "john_doe" 1; "jane_smith" 1; # Add more valid users as needed } server { listen 80; server_name your-domain.com; # Your existing auth setup auth_request /auth; auth_request_set $auth_resp_x_auth_user $upstream_http_x_auth_user; # Now use the mapped variable to restrict access # Example 1: Block all invalid users at the server level if ($is_valid_user = 0) { return 403; } # Example 2: Restrict only specific locations location /protected { if ($is_valid_user = 0) { return 403; } # Your protected location config here } } }
Pro tips for this approach:
- Test that
$auth_resp_x_auth_useris being set correctly first (addadd_header X-Debug-User $auth_resp_x_auth_user;temporarily to see the value in response headers). - Wrap usernames in quotes if they contain special characters (like spaces,
@, or dots), e.g.,"user@example.com" 1;. - Avoid overusing
ifin Nginx for complex logic (it can have unexpected behavior), but for simplereturncases like this, it's safe.
2. Use Lua (for dynamic logic or avoiding map in http block)
If you're using OpenResty (or have Nginx compiled with the lua-nginx-module), you can handle the validation directly in your server or location block without touching the http block. This is great if your valid user list changes often, or if you want more flexible logic.
Example config:
server { listen 80; server_name your-domain.com; auth_request /auth; auth_request_set $auth_resp_x_auth_user $upstream_http_x_auth_user; location /protected { # Use Lua to check if the user is valid access_by_lua_block { local valid_users = { ["john_doe"] = true, ["jane_smith"] = true # Add more users here } -- Check if the user exists in the valid_users table if not valid_users[ngx.var.auth_resp_x_auth_user] then ngx.exit(403) -- Forbid access if invalid end } # Your protected location config here } }
Why this works:
The access_by_lua_block runs after auth_request, so $auth_resp_x_auth_user is already set. You can even extend this to pull valid users from a database or API if needed, which is way more flexible than a static map.
Which one should you choose?
- Go with the
mapapproach if you have a fixed list of valid users and want a simple, native Nginx solution. - Use Lua if you need dynamic user lists, complex validation logic, or prefer keeping all related config in the
server/locationblock.
内容的提问来源于stack exchange,提问作者Rino Bino

