らっちゃいブログ

日々の学びと気づきを発信するブログ

Django REST frameworkでAPIにアクセス権を実装する方法

Django REST framework シリーズです。今回はアクセス権のお話をします。

Django REST framework を使ったことがないという方はこちらをどうぞ。

racchai.hatenablog.com

はじめに

API を実装する上で欠かせないのが、アクセス権の管理ですね。API 毎に実行可能かどうかをチェックする処理を入れるのは大変ですし、対応漏れも起きやすいです。かといって、自前で共通化するのも大変ですね。

Django REST framework では permission という概念でAPI毎にアクセス権を設定できるようになっていますので、本記事ではよくあるアクセス権を例に挙げて実装方法について紹介してみようと思います。

具体的な解説に入る前に、サンプルのAPIを作っておきます。

api.py

from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

class SampleView(GenericAPIView):
    permission_classes = ()

    def get(self, request, format=None):
        return Response()

urls.py に以下を追加。

url(r'^sample', SampleView.as_view()),

SampleView に見慣れない permission_classes というフィールドが登場しましたが、Django REST framework ではここに Permission クラスを設定することでアクセス権を設定するようになります。

認証済みの場合のみアクセスさせたい

お決まりのやつですね。認証済みかどうかを検証するパーミッションについては、 Django REST Framework にて標準で用意されている IsAuthenticated がありますので、こちらを使うだけです。

from rest_framework.generics import GenericAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

class SampleView(GenericAPIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        return Response()

permission_classes に IsAuthenticated を指定しました。これで認証済みでないと実行できないAPIとなります。

管理者のみアクセス可能

これもよくあるパターンですね。今回は特定のメールアドレス(admin@racchai.com)であれば管理者として判定するパーミッションを作成してみます。

作り方は簡単で、rest_framework.permissions.BasePermission を継承したクラスにて has_permission 関数を定義するだけです。has_permission 内でアクセス可能な条件を設定してあげれば、それだけでパーミッションクラスの完成となります。

from rest_framework.generics import GenericAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.permissions import BasePermission 

class IsAdmin(BasePermission):
    def has_permission(self, request, view):
        return request.user and request.user.email == 'admin@racchai.com'

class SampleView(GenericAPIView):
    permission_classes = (IsAdmin,)

    def get(self, request, format=None):
        return Response()

IsAdmin パーミッションを作成し、それを SampleView に設定しました。たったこれだけで、管理者しかアクセスできないAPIとなりました。

管理者のみ変更可能でそれ以外は閲覧のみさせたい

さきほど作成した IsAdmin パーミッションをさらに発展させてやるだけで実現できますね。新しいパーミッションIsAdminOrReadOnly として作成します。

from rest_framework.generics import GenericAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.permissions import BasePermission, SAFE_METHODS

class IsAdmin(BasePermission):
    def has_permission(self, request, view):
        return request.user and request.user.email == 'admin@racchai.com'

class IsAdminOrReadOnly(BasePermission):
    def has_permission(self, request, view):
        return request.method in SAFE_METHODS or IsAdmin().has_permission(request, view)

class SampleView(GenericAPIView):
    permission_classes = (IsAdminOrReadOnly,)

    def get(self, request, format=None):
        return Response()

    def post(self, request, format=None):
        return Response()

閲覧かどうかは、HTTP メソッドの種類で判別します。フレームワークの方で SAFE_METHODS(GET, HEAD, OPTIONS) が定義されているので、リクエストメソッドがそのどれかであれば True を返します。SAFE_METHODSでない場合は、IsAdmin パーミッションを評価することで実行可能かを判定するようになっています。

まとめ

簡単すぎてつまらない内容だったかもしれませんね。本当はパーミッションの仕組みでオブジェクトベースのアクセス権を設定することもできるのですが、長くなりそうなのでそれはまた別な機会にご紹介することにします。

それでは今回はこのへんで!

喉が痛いときはヴィックス一択でしょ。異論は認めない

朝起きたら風邪っぽくて喉が痛かったので、朝一でヴィックスをキメました。

イソジンでうがいとか別な薬飲んでも全く効かないけど、ヴィックスは即効性があってよく効くのでいつもお世話になってます。ただののど飴だと思われるかもしれませんが、医薬部外品とは思えない効果なので使ったことがない方はぜひ一度お試しください。

レモンフレーバーがおなじみ(?)ですが、最近は着色料などを気にしてレギュラータイプも買うようになりました。

ヴィックスとユンケル黄帝液があればもう風邪なんて怖くないですね!

Nginx 1.11 がリリースされました

http://nginx.org/en/CHANGES

変更点はこちら。

*) Feature: the "transparent" parameter of the "proxy_bind",
   "fastcgi_bind", "memcached_bind", "scgi_bind", and "uwsgi_bind"
   directives.

*) Feature: the $request_id variable.

*) Feature: the "map" directive supports combinations of multiple
   variables as resulting values.

*) Feature: now nginx checks if EPOLLRDHUP events are supported by
   kernel, and optimizes connection handling accordingly if the "epoll"
   method is used.

*) Feature: the "ssl_certificate" and "ssl_certificate_key" directives
   can be specified multiple times to load certificates of different
   types (for example, RSA and ECDSA).

*) Feature: the "ssl_ecdh_curve" directive now allows specifying a list
   of curves when using OpenSSL 1.0.2 or newer; by default a list built
   into OpenSSL is used.

*) Change: to use DHE ciphers it is now required to specify parameters
   using the "ssl_dhparam" directive.

*) Feature: the $proxy_protocol_port variable.

*) Feature: the $realip_remote_port variable in the
   ngx_http_realip_module.

*) Feature: the ngx_http_realip_module is now able to set the client
   port in addition to the address.

*) Change: the "421 Misdirected Request" response now used when
   rejecting requests to a virtual server different from one negotiated
   during an SSL handshake; this improves interoperability with some
   HTTP/2 clients when using client certificates.

*) Change: HTTP/2 clients can now start sending request body
   immediately; the "http2_body_preread_size" directive controls size of
   the buffer used before nginx will start reading client request body.

*) Bugfix: cached error responses were not updated when using the
   "proxy_cache_bypass" directive.

個人的に気になったのは

  • $request_id 導入
    • リクエストIDをヘッダーに付与することができると何かと便利に使えそう
  • ssl_certificate / ssl_certificate_key を複数回指定できる
    • RSA と ECDSA の証明書をデュアルで指定できたりする
  • HTTP/2 でも proxy_request_buffering off のような挙動にできるようになった(と理解した)
    • 以前記事にしたようなことが HTTP/2 でも回避できるんじゃないかと期待 racchai.hatenablog.com

あたりでしょうか。

開発者ブログにて nginScript は 1.11.x で入ると書いてありましたし、今後のアップデートが楽しみですね!

日本酒が送られてきたがもう限界かもしれない

自宅のインターホンがなったので出てみたら、宅急便だった。

運送屋さんが苦しそうな声で『お届け物です』と巨大なダンボールを抱えている。見るからに重そうだ。

はて、こんなデカイもの発注した記憶ないぞ。妻が内緒で何か買ったかな。いやいや、こんなデカイもの内緒で買っても隠すとこないだろ。部屋狭いんだから。

おっと。ゆっくり考えてる場合ではない。そうこうしてるうちに運送屋さんのライフがゼロになりそうだ。受け取ると、重さがずっしりくる。そしてひんやりしている。クール便らしい。

受取人を見ると、妻の名前が書かれている。この重量でクール便・・・カツオでも一本丸々買ったかな。

おっと。ゆっくり考えてる場合ではない。運送屋さんが早く出発したそうにこちらを見ている。サインするの忘れてた。

サインを書きながら送り主をチラ見したところ、見覚えのある名前が。お義父さんだ。一瞬にして全ての謎が解けた。中身は酒だ。間違いない。

運送屋さんにお礼をして開封してみると、案の定だった。巨大なダンボールの四隅に一本ずつ一升瓶が配置されている。

驚きながらも中身を取り出してみると、獺祭が入っている。しかも二本。残り二本は飲んだことはない銘柄だったが、おいしそうだ。これはすごいな。

クール便できたわけなので、当然要冷蔵だろう。さっそくそれらを冷蔵庫へ・・・となるわけだが、よく考えると我が家の冷蔵庫にそんな余裕はない。というか一般家庭の冷蔵庫に一升瓶四本を収容するのは至難の業だ。中身を取り出すしかない。

!!

そうか。中身を取り出せばいいのか。

目をつけたのは野菜室だ。野菜たちにそんな上等な保存場所はいらないだろう。常温世界へようこそ。

5分後

我が家の野菜室は日本酒で埋め尽くされた。やればできるもんだ。しかし、もはや何も入らない状態となってしまった。

こうして我が家の冷蔵庫は限界をむかえた。(オチ弱め)

Linuxのbase64コマンドでハマったのでメモ

今日は小ネタで失礼します。

ベーシック認証のトークン作るのに base64 コマンド使ったんですが、どうも認証が通らない。

base64 コマンド自体はこんな感じで叩きました。

$ echo "user:pass" | base64
dXNlcjpwYXNzCg==

ちゃんと作れてるように見えます。デコードしてみても、合ってそうです。

$ echo "dXNlcjpwYXNzCg==" | base64 -d
user:pass

なぜ認証が通らないか?

それは echo が改行コードも出力していたから!

$ echo "dXNlcjpwYXNzCg==" | base64 -d
user:pass[LF] ←実際にはここに改行コードが入ってた

というわけで、echo コマンドに -n オプションを与えて改行を出力しないように修正したら無事認証が通りましたとさ。

$ echo -n "user:pass" | base64
dXNlcjpwYXNz

我ながらしょうもないミスをしたものだ。。

確定申告するなら年末調整しておけ

今回はサラリーマンの方向けの記事です。

副業、ローン控除の申請等で確定申告をする機会があろうかと思います。そんなときふと疑問に思うのが、確定申告するなら会社で年末調整しなくていい(してはいけない)のでは?ということ。なんとなく、両方やったら二重で申告してるような気分になりますからね。

友人は疑うことなく会社に『今年は確定申告するので年末調整は不要です(キリッ)』とキメたそうです。

別にこれが間違っているわけではありません。しかし、友人に関しては年末調整もしておくべきでした。理由は後述します。

そもそも年末調整とは何なのでしょうか?所得から各種控除額を差し引くことで、払い過ぎた税金を返してもらうというだけの制度ですよね。払い過ぎた税金を返してもらうことなら、確定申告でも可能です。ですので、確定申告するなら年末調整しなくても良いというのはあながち間違っていません。

ですが、個人的には年末調整はしておくことをお勧めします。なぜかといいますと、その方が確定申告が楽だからです。

サラリーマンなら毎年源泉徴収票を会社から受け取りますね?確定申告では源泉徴収票に記載されている数字を確定申告書に転記していく作業があるわけですが、年末調整していない場合、会社からほぼ空欄の源泉徴収票を渡されます。年収額くらいしか書いてありません。

空欄だらけの源泉徴収票を受け取った後待っているのは、空欄を自分で埋める作業です。何を埋めないのかを調べ、税務署のサイト等から対象の計算式を見つけ出し、自分の条件に合わせて計算しなければなりません。私も一度経験しているのでわかりますが、初めてこの作業をやったときは本当にしんどかったです。

所得額等に応じて計算式は違うし、似たような用語も多くて使った計算式自体が正しいのかすらわからない。そして当然計算結果にも自信がない。不安過ぎる。

ほぼ空欄の源泉徴収票を受け取った友人の言葉です。このころ泣き言ばかりいってましたね。こんな言葉を発するほどの不安を抱えるくらいなら、年末調整しておけばいいのです。

では結論です。

確定申告するときも年末調整はしておけ!

っと、結論書いた後ですが、もう一点。

税金やもろもろの計算に興味があって、自分で計算して理解を深めたい!という方にも一言。

悪いことは言いません、年末調整しといてください。自分で計算するのは止めませんが、答え合わせはできた方がいいですからね。

以上!

BOSEのSoundLink Mini II を半年間使って得たもの

SoundLink Mini II との出会い

今年の正月の話だ。珍しく自宅で年を越したため、近くのショッピングモールの初売りに行くことになった。行ってみると、なかなかの混雑ぶりだ。どの店も福袋に群がる人、人、犬、人。他人を押しのける能力に欠けるため、全く福袋にたどり着けない。

もう帰りたい。

そう思ったとき、ほとんど人のいない店舗があることに気づいた。BOSE だ。そういえばスピーカーがほしかったことを思い出し、話を聞いてみることにした。

ここにも福袋は存在していた。中身が丸見えだったので覗いてみると、こちらの商品が入っていた。

店頭価格では、スピーカー単体だと 25,000 円で販売されていた。

オプションとして専用カバーと持ち運び用のケースが入っていた。

以上3点で3万円だった。オプション品も含めると35,000円相当なのだそうだ。

ちなみにケースは上のもので合っていたか記憶が定かではない。先日どこかにいってしまった。

購入まで

まずは音質を確認してみる。一番のチェックポイントは低音だ。重低音を楽しめないくらいならスピーカーなどいらないとすら思っている。

ちなみに低音のチェックには JET を流すことにしている。しっとり系で低音の主張が強い曲が多いのだ。これならば多少音量を上げても周りに迷惑をかけることがない。

若い頃は JET のこちらのアルバムを流して寝るのがお気に入りだった。

Get Born

Get Born

あの頃使っていたコンポは当時としては音質はよかったが、いま思えばおもちゃ同然だ。

話を戻す。

再生してみると重低音がしっかり出ている。いや、しっかりどころではない。腹に響いてくる。

『このサイズ、価格でこの品質!買います!』

即買いだった。去年一年がんばった自分へのご褒美だ。ウキウキで帰宅して即座にセッティングした。

使い倒す

お店では良く感じたが、いざ家で使ってみるとそうでもないことに気付くということがこれまで多々あった。しかし、今回は問題なかった。家でもあの音質が楽しめた。

素晴らしいのが、本体が非常にコンパクトで Bluetooth 付きなので、再生しながらどこにでも持ち運ぶことができる。

作業デスクの上に置けば、作業用BGMをライブ感満載で楽しむことができる。リビングに置けば、娘に異常な音質のアンパンマンを聴かせてやることができる。テレビにも(有線ではあるが)つながるので、録画しておいた映画をホームシアター的に堪能することも可能だ。低音の響くCMは普段とは別物なのでぜひ試してもらいたい。寝室に置けば、また昔のように JET を聞きながら寝ることもできるだろう。さすがに寝室への設置は妻に怒られるのでまだやっていない。

防水ではないのでお風呂場への設置はNGだ。脱衣所までで我慢しよう。

半年後

これまで安いスピーカーを購入したことがあったが、ことごとく使わなくなってゴミとなった苦い思い出がある。今回はテレビに接続可能であるため、テレビの横に常備することにした。そのおかげで、存在を忘れることがない。半年経ったいまでも、音楽を聴きたいときはその場で Bluetooth 接続しているし、テレビで野球やサッカーのスポーツ観戦するのにも活躍している。

しかし、この世に完璧な買い物などない。

これだけ満足度が高くても、一点だけ後悔していることがある。

福袋で買う必要はなかった

これだ。これに尽きる。

数日前にコストコに行ったら単体で 20,000 円で売っていた\(^o^)/

その衝撃がこの記事を書くきっかけにもなっている。

福袋に同梱されていた外出用のケースは一度も外に持ち出すことなく紛失している。開封すらした覚えがない。そもそも極度のインドア派であるため、持ち出したときのことなど懸念する必要がないのだ。バーベキューに持ってったら楽しいかも!なんて実現しそうにもないことを加味したのが間違いだった。

唯一、専用カバーだけは活躍している。これのおかげで娘がテレビ台から落としたりかじりついても多少安心できるのだ。

ただ、カバーに関しても無いなら無いでいいとも思っている。

勢いで福袋なんて買わないで最安値を調べて単体で買えばよかった。うわーん。

まとめ

半年間使って得たもの。それは教訓だ。

電化製品は単体を最安値で買え

オプション品は必要になってから買え

この二つを深く心に刻んでいただきたい。

以上、基本中の基本を学んだという話でした。