Help us understand the problem. What is going on with this article?

Nginxで認証付きのキャッシュを実装する

More than 3 years have passed since last update.

実現したいこと

Nginxを使ってアプリケーションサーバーのレスポンスをキャッシュしたいケースは多いと思いますが、
厄介なのが認証が必要なケースです。単純にキャッシュしてしまうと認証が回避されてしまいます。
仕方ないので認証が必要なリクエストは毎回アプリケーションサーバに流すとなると、やはりパフォーマンスは下がってしまいます。
なんとか認証をアプリケーションサーバを介さずに実現し、高速な認証つきのキャッシュを実現できないか考えてみました。

仕組み

例えば、リクエストヘッダーなどに認証トークンが付いており、これをMemcachedに問い合わせることで認証をチェックできるというシステムである場合、どうやらNginxの既存のモジュールだけで実現できることがわかりました。
使うのはproxy_cacheの他に下記の2つの標準モジュールです。

  • ngx_http_auth_request_module
  • ngx_http_memcached_module

ngx_http_auth_request_moduleに含まれるauth_requestというディレクティブを使うと、指定したURIのレスポンスが
正常系(2xx)である場合だけリクエストを処理させることができます。
ngx_http_memcached_moduleは、$memcached_key変数に指定したキーの内容をmemcached_passディレクティブで指定した
ホストから取得するといったことができるモジュールです。キーがあればステータス200ですが存在しない場合は404となります。

memcachedの内容を返すURIを用意しておき、auth_requestを使ってそれを認証URIにすれば、認証つきのキャッシュを実現できます。

設定例

前提となる構成と認証

アプリケーションサーバ: 127.0.0.1:8080
Memcachedサーバ: 127.0.0.1:11211
認証:リクエストヘッダX-TOKENに認証用のトークンが設定される。Memcachedサーバには有効な認証トークンだけがキーとして設定されている。

nginx.conf
http {
    proxy_cache_path /var/cache/nginx/cache levels=1 keys_zone=zone:4m inactive=7d max_size=50m;

    upstream backend {
        server 127.0.0.1:8080;
    }

    server {
        location / {
            auth_request /auth;
            proxy_pass http://backend;
            proxy_cache zone;
            proxy_cache_key $scheme$proxy_host$uri$is_args$args;
            proxy_cache_valid  200 1d;
        }
        location /auth {
            set $memcached_key "$http_x_token";
            memcached_pass 127.0.0.1:11211;
        }
    }
}

Memcachedの部分は実際にはDBやRedisへの問い合わせが必要だったり、単なる認証だけでなく複雑なアクセス条件が必要だったり
様々なケースがあると思います。その場合、組み込みのLuaを使うか、認証やアクセス条件のチェックを高速に処理する専用のサーバを用意するというのも良い策な気がします。

devneko
フリーのプログラマです。 ウェブシステム開発、スマホアプリ開発にフルスタックで対応可能です。
http://blog.devneko.net/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした