それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

nginx で サイトを認証を手軽にログインフォーム認証にする。(Basic認証の代わり)

nginx で サイトを認証する。

Basic認証だと不便なので、フォーム認証をする。

巷に「nginxでbasic認証してみた」の記事が溢れているけど。どう考えてもbasic認証(digest認証)よりHTTP認証(フォーム)のほうがいいと思うんですよね。nginxだけで片付くのになんでやらないんだろう。

nginx の auth_request を使う。

auth_requestで、認証が出来る。

  • 認証済みの場合は、指定したURLをそのまま見せる
  • 未認証の場合は、認証用のページに飛ばす。
  • 認証ページが、401/403 を返せば未認証に
  • 認証ページが、200(20x)を返せば認証済みに。

要は、認証ページを指定して403 / 200 を返す。

簡単!!!!

それだけ。超簡単。

ログインフォームに転送するには nginx で 401 エラーページを指定する

もしかしたらBasic/Digest認証を設定するよりもっと簡単で使いやすいのでは。

設定はこれだけ

auth_request /auth_checker.php;
error_page 401 =301  https://$host/form.php?orig=$uri&$query_string;
auth_request  セッションチェックURL

上記のこれで、ユーザの認証状況を確認する。

error_page 401 =302  ログインフォームURL

上記のこれで、401が来たら、302 でリダイレクトに変換して、認証ページへ飛ばしてる。

認証取得ページで、認証完了後に元のURLへ再度リダイレクトをするために、LOGIN_URL?orig=$uri&$query_string で認証ページに元のリクエストページを保存している。

認証チェックの例

認証チェックは、セッションなどを見て、200 / 402 をチェックすればいい 使い方によっては、IPアドレスでチェックしたり、Oauthなどもできそうですよね。

例 auth_checker.php

<?php
if ( empty($_COOKIE) ){
     //do something for cookie
}
session_start();
if ( !empty($_SESSION['is_login']) ) {
  http_response_code(200);
  return ;
}else{
  http_response_code(401);
  return ;
}

特定のディレクトリにだけ認証をかけたい場合

location /path/to/秘密 {

    auth_request /auth_checker.php;
    error_page 401 =302  https://$host/form.php?orig=$uri&$query_string;
}

未認証のときは、単に見せない(ログイン者だけ画像が見えるなど)であれば、 error_pageのリダイレクトは無くても良い。

個人的には歓喜した。

Apacheディレクトリの一覧に保護を掛けるのが楽。 Basic認証だとiOSがパスワードを学習しないので不便なのでした。

認証を作るのが面倒くさいので、割とコレで自分ファイルにロックを掛けるだけなら、手軽でいいなとおもいます。

ファイルの共有程度に、NextCloudいれたりGoogleDrive契約するのも面倒くさい話だし。

参考資料

http://nginx.org/en/docs/http/ngx_http_auth_request_module.html

2018-05-09 更新

リダイレクトには、301 より 302 の方が良さそう。Chromeが301 リダイレクトを学習してキャッシュしてしまう。