概要
「nginxで認証用proxyサーバを作成」をもとに設定
全てのアクセスでわざわざPHPを呼び出すのは非効率なので、セッションの判定部分はNginxのみで解決することにより高速化可能
http://blog.asial.co.jp/1046
GOAL
cookieにauthidというキーで、ランダム値を保存
memcachedにランダム値をキーにして、認証状態(1)をセット
cookieとmemcachedの値から、ログインしているかどうかを判定する
今回はランダム値を”abcde”とする
できればサードパーティのモジュールevalは利用しない方向で検討する
各バージョン
root@hostname:/home/shimizu# uname -a Linux hostname 3.2.0-4-amd64 #1 SMP Debian 3.2.54-2 x86_64 GNU/Linux root@hostname:/home/shimizu# memcached -h memcached 1.4.13 root@hostname:/home/shimizu# nginx -v nginx version: nginx/1.2.1 TLS SNI support enabled configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-pcre-jit --with-debug --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_realip_module --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_xslt_module --with-ipv6 --with-sha1=/usr/include/openssl --with-md5=/usr/include/openssl --with-mail --with-mail_ssl_module --add-module=/tmp/buildd/nginx-1.2.1/debian/modules/nginx-auth-pam --add-module=/tmp/buildd/nginx-1.2.1/debian/modules/nginx-echo --add-module=/tmp/buildd/nginx-1.2.1/debian/modules/nginx-upstream-fair --add-module=/tmp/buildd/nginx-1.2.1/debian/modules/nginx-dav-ext-module
memcached
memcachedにkeyを設定する
root@hostname:/var/nginx# telnet localhost 11211 Trying ::1... Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. set abcde 0 0 1 1 STORED get abcde VALUE abcde 0 1 1 END quit
keyの中身をGUIで確認する
root@hostname:/var/www/htdocs# wget -d http://livebookmark.net/memcachephp/memcachephp.zip
DEBUG output created by Wget 1.13.4 on linux-gnu.
URI encoding = `UTF-8′
–2014-07-11 22:52:38– http://livebookmark.net/memcachephp/memcachephp.zip
livebookmark.net (livebookmark.net) をDNSに問いあわせています… 108.61.16.67
Caching livebookmark.net => 108.61.16.67
…(中略)
root@hostname:/var/www/htdocs# unzip memcachephp.zip
Archive: memcachephp.zip
inflating: memcache.php
root@hostname:/var/www/htdocs# chown www-data:www-data memcache.php
root@hostname:/var/www/htdocs# vi memcache.php
==================
$MEMCACHE_SERVERS[] = ‘localhost:11211’; // add more as an array
//$MEMCACHE_SERVERS[] = ‘mymemcache-server2:11211’; // add more as an array
==================
※phpからmemcachedに設定した場合、有効期限はphp.iniのsession.gc_maxlifetimeが使用される
cookieを設定する
root@hostname:/var/www/htdocs# vi setcookie.php ===== <?php setcookie("authid", "abcde"); echo "get cookie!" ?> =====
setcookie.phpにアクセスする
cookieを確認する
root@hostname:/var/www/htdocs# vi getcookie.php ===== <?php var_dump($_COOKIE); ?> =====
ブラウザからgetcookie.phpにアクセスすると
array(2) { ["__atuvc"]=> string(4) "6|28" ["authid"]=> string(5) "abcde" }
ブラウザの設定画面から
nginx + memcached その1
upstream memcache { server 127.0.0.1:11211; } server { root /var/www/htdocs; index index.html index.htm; server_name x.x.x.x; location / { set $memcached_key abcde; memcached_pass memcache; default_type "text/html; charset=utf-8"; error_page 404 = @notkey; } location @notkey { proxy_pass http://www.google.co.jp; } }
memcached_passディレクティブは、キー検索を実施する際に$memcached_key変数を利用する
対応するkeyが存在しない場合は、error_page 404となり、上記場合はhttp://www.google.co.jpに転送される
対応するkeyが存在した場合はvalueを返す
通常はvalueにキャッシュを保存して利用する
nginx + memcached その2
location / { if ($cookie_authid) { set $memcached_key $cookie_authid; memcached_pass memcache; default_type "text/html; charset=utf-8"; error_page 404 = @notkey; } }
HTTPモジュールで$cookie_nameは、nameという名前のcookieの値と定義されている
つまり、$cookie_authidはauthidの値が入る
…ただしmemcached_passにはvalueを返すしかできず、evalモジュールが必須のようなので他の方法を模索してみる
ngx_http_map_moduleの利用
map $cookie_authid $cookie_flag { abcde 1; default 0; } server { root /var/www/htdocs; index index.html index.htm; server_name 49.212.204.46; location / { if ( $cookie_flag = 0 ){ proxy_pass http://www.google.co.jp; } if ( $cookie_flag = 1 ){ proxy_pass http://www.yahoo.co.jp; } }
cookieのauthidの値がabcdeのときは、$cookie_flagを1に、それ以外は0にする
cookieの値に応じて動作を変更できるが、、cookieの値を変更するたびに設定を変更する必要がある、、他の方法を模索する
ngx_http_userid_moduleの利用
cookieを操作するモジュール、apacheでいうところのmod_uid
location / { userid on; userid_name authid_userid; userid_domain 49.212.204.46; userid_path /; userid_expires 365d; }
/にアクセスすると、cookieが設定される
userごとにcookieを設定し、logformatで$uid_gotを利用するとcookieの値が取得できるため、ユーザの動きを確認できるが、、今回の要件とは合わないため他の方法を模索する
lua-nginx-moduleの利用
Note that the ngx_eval module can be approximated by using rewrite_by_lua
nginx-extrasパッケージをインストールし、この手法で実現した!
location / { # ファイルが存在する場合 if (-f $request_filename) { rewrite_by_lua ' local res = ngx.location.capture("/auth") if res.status == ngx.HTTP_OK then ngx.exit(ngx.OK) else return ngx.redirect("http://www.google.co.jp/") end '; break; } # ファイルが存在しなかった場合 if (!-e $request_filename) { rewrite ^(.*)$ http://www.yahoo.co.jp permanent; } } location /auth { internal; set $memcached_key $cookie_authid; memcached_pass 127.0.0.1:11211; }
- rewrite_by_luaでngx.exit(ngx.OK)を利用すると、nginxはcontentハンドラの処理に移る
おまけ-S3との連携
参考
http://livebookmark.net/journal/2008/05/21/memcachephp-stats-like-apcphp/
http://qiita.com/akiko-pusu/items/aae6be5fe4b77f588a80
http://wiki.nginx.org/HttpLuaModule