バックエンドエンジニアになるための基礎知識を学習する

バックエンドエンジニアロードマップ

Webを支える技術

リソース:Web上に存在する、名前を持ったありとあらゆる情報
URI:リソースの名前
・技術評論者のページ

Restのアーキテクチャスタイル
クライアント/サーバのアーキテクチャを採用
・クライアントがサーバにリクエストを送り、サーバーはそれに対してレスポンスを返す
ステートレスサーバ
・クライアントのアプリケーション状態をサーバーで管理しないこと
キャッシュ
・一度取得したリソースをクライアント側で使い回す方式
統一インタフェース
・HTTP 1.1ではGETやPOSTなど8個のメソッドが定義されている
コードオンデマンド
・プログラムコードをサーバーからダウンロードし、クライアント側でそれを実行する
・JavaScriptなどが該当する

① URI
・Web上に存在するリソースは全てURLで指し示すことができる。
② URIの構文
・URIスキーム:http(そのURIが利用するプロトコル)
・ホスト名:blog.example.jp(DNSで名前が解決できるドメイン名)
・パス:/entries/1(ホストの中でリソースを一意に指し示す)
③ 複雑なURIの例
・URIスキーム:http
・ユーザー情報:youhei:pass(このリソースにアクセスする際に利用するユーザ名とパスワード)
・ホスト名:blog.example.jp
・ポート番号:8000(デフォルト80番)
・パス:/search
・クエリパラメータ:q=test&debug=true(q=testがクエリ。1つ以上のクエリの集合をクエリパラメータという)
・URIフラグメント:#n10
④ URIで使用できる文字
・アルファベット:AZaz・数字:09・記号:.~:@!$&'()
⑤ URIの長さ制限
・仕様上はURIの長さに制限はない。
⑥ URIの設計指針
・URIにプログラミング言語依存の拡張子を利用しない(.pl、.rb、.do、.jspなど)
・URIに実装依存のパス名を利用しない(cgibin、servletなど)
・URIにプログラミング言語のメソッド名を利用しない
・URIにセッションIDを含めない
・URIはそのリソースを表現する名詞である

① HTTP
・Web上でやりとりするリソースの表現を、クライアントとサーバの間でやり取りするためのプロトコル
・クライアントはHTTPに従ってサーバにリクエストを送り、レスポンスを得る
② HTTPメッセージの構成要素
スタートライン:1行目はスタートラインと総称されている。リクエストメッセージの場合はリクエストライン、レスポンスメッセージの場合はステータスラインです。
ヘッダ:ヘッダの終了は空行で識別する。
空行:
ボディ:ボディにはテキストだけでなく、バイナリデータも入れられる。

① HTTPメソッド
HTTP 1.1は8つのメソッドが定義されている。
GET リソースの取得
POST 子リソースの作成、リソースへのデータ追加、そのほかの処理
PUT リソースの更新、リソースの作成
DELETE リソースの削除
HEAD リソースのヘッダの取得
OPTIONS リソースがサポートしているメソッドの取得
TRACE 自分宛にリクエストメッセージを返す(ループバック)試験
CONNECT プロキシ動作のトンネル接続への変更
Create 作成 POST/PUT
Read 読み込み GET
Update 更新 PUT
Delete 削除 DELETE
GET
【リクエスト】
GET /list HTTP/1.1
Host: example.jp
【レスポンス】
HTTP/1.1 200 OK
Content-Type: application/json
[
{"uri": "http://example.jp/list/item1"},
{"uri": "http://example.jp/list/item2"},
{"uri": "http://example.jp/list/item3"},
]
POST
【リクエスト】
POST /list HTTP/1.1
Host: example.jp
Content-Type: text/plain; charset=utf-8
こんにちは!
【レスポンス】
HTTP/1.1 201 Created
Content-Type: text/plain; charset=utf-8
Location: http://example.jp/list/item4
こんにちは!
PUT(リソースの更新)
【リクエスト】
PUT /list/item4 HTTP/1.1
Host: example.jp
Content-Type: text/plain; charset=utf-8
こんばんは!
【レスポンス】
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-i
こんばんは!
PUT(リソースの作成)
【リクエスト】
PUT /newitem HTTP/1.1
Host: example.jp
Content-Type: text/plain; charset=utf-8
新しいリソース/newitemの内容
【レスポンス】
HTTP/1.1 201 Created
Content-Type: text/plain; charset=utf-8
新しいリソース/newitemの内容
※特別な理由がない限りは、リソースの作成はPOSTで行いURIもサーバ側で決定するという設計が望ましい。
DELETE
【リクエスト】
DELETE /list/item2 HTTP/1.1
Host: example.jp
【レスポンス】
HTTP/1.1 200 OK
GET、HEAD べき等かつ安全
PUT、DELETE べき等だが安全でもない
POST べき等でも安全でもない
べき等:ある操作を何回行っても結果が同じこと
安全:操作対象のリソースの状態を変化させないこと
② ステータスコード
③ ヘッダ

ステータスコード
・1xx: 処理中(処理が継続していることを示す)
・2xx: 成功(リクエストが成功したことを示す)
・3xx: リダイレクト(他のリソースへのリダイレクトを示す)
・4xx: クライアントエラー(原因はクライアントのリクエストにある)
・5xx: サーバエラー(原因はサーバ側にある)
・200 OK リクエスト成功
・201 Created リソースの作成成功
・301 Moved Permanently リクエストで指定したリソースが新しいURIに移動したことを示す
・303 See Other 別URIの参照
・400 Bad Request リクエストの間違い
・401 Unauthorized アクセス権不正
・404 Not Found リソースの不在
・500 Internal Server Error サーバ内部エラー
・503 Service Unavailable サービスの使用停止(サーバメンテナンスなどで一時的にアクセスできない場合)

HTTPヘッダ
Content-Type(メディアタイプを指定する)
そのメッセージのボディの内容がどのような種類なのかメディアタイプで示す
text 人が呼んで直接理解できるテキスト text/plain
image 画像データ image/jpeg
video 動画データ video/mp4
application そのほかのデータ application/pdf
charsetパラメータ(文字エンコーディングを指定する)
charset=utf-8
Content-Languageヘッダ
Content-Language: ja-JP
Pragma(キャッシュを抑制する)
Pragma: no-cache (リソースをキャッシュしてはならないことを示す)
Expires(キャッシュの有効期限を示す)
Expires: Thu, 11 May 2010 16:00:00 GMT
Cache-Control(詳細なキャッシュ方法を指定する)
Cache-Control:no-cache(Pragmaの時と同じ意味)

ハイパーメディアフォーマット
① HTML
② mictoformats
③ Atom
④ Atom Publishing Protocol
⑤ JSON

JSON
JavaScript Object Notationの略
RFC 4627が規定するデータ記述言語
Content-Type: application/json; charset=utf-8
データ型
JSONに組み込みで用意されているデータ型には6つある
・オブジェクト
・配列
・文字列
・数値
・ブーリアン
・null

振り返り
この本は技術力を上げていき、1年に1回読み返すことで理解が深まっていく本だと思いました。
そのくらい内容が濃くて、理解できない箇所が多いと思います。

バックエンドエンジニアおすすめの本

Web API: The Good Parts
Web APIを開発するに際して、どのように設計をすれば良いのか、どのような点に気をつけて開発をすれば良いのかについて書かれた書籍
一旦、上記の本の要約となりそうな記事を読んでみました。

第1章 Web APIとは何か
HTTPプロトコルを利用してネットワーク越しに呼び出すAPI
APIは機能を外部から呼び出すための仕様のこと
Web APIの設計を学ぶ理由
・良い設計のWeb APIは使いやすい
・良い設計のWeb APIは変更しやすい
・良い設計のWeb APIは頑強である(セキュリティが考慮されているかなど)
重要な原則
・仕様が決まっているものに関しては仕様に従う
・仕様が存在していないものに関してはデファクトスタンダードに従う

第2章 エンドポイントの設計とリクエストの形式
良いURIの設計をするために重要な原則
・覚えやすく、どんな機能を持つURIなのかがひと目でわかる
良いURIの設計をするためのポイント
・短く入力しやすいURI
・人間が読んで理解できるURI
・大文字小文字が混在していないURI
・改造しやすいURI
・サーバ側のアーキテクチャが反映されていないURI
・ルールが統一されたURI
メソッドの例
GET リソースの取得
POST リソースの新規登録
PUT 既存リソースの更新
DELETE リソースの削除
PATCH リソースの一部変更
HEAD リソースのメタ情報の取得
POSTを利用して、メタ情報として本当はこのメソッドを使いたいということをサーバに送信する
・この場合は、X-HTTP-Method-OverrideにDELETEを設定し、DELETEを実行する
POST /v1/users/123 HTTP/1.1
Host: api.example.com
X-HTTP-Method-Override: DELETE
・この場合は、_methodに実行したいメソッドを記載する
user-testuser&_method=PUT
検索APIの絞り込みのためのパラメータ
http://api.linkedin.com/v1/people-search?first-name=Clair
1スクリーン1APIコール、1セーブ1APIコールという言葉があり、一つの画面を表示するためにコールするのが1つのAPIで済むようにそれに合わせたAPIを用意し、何らかのデータをサーバに保存する場合にも1回のコールで済むようにそれに合わせたAPIを用意する方が良い
REST APIに至るための設計レベル
・LEVEL0 HTTPを使っている
・LEVEL1 リソースの概念の導入
・LEVEL2 HTTPの動詞(GET/POST/PUT/DELETEなど)の導入
・LEVEL3 HATEOASの概念の導入
HATEOAS(hypermedia as the engine of application state)はAPIの返すデータの中に、次に行う行動、取得するデータなどのURIをリンクとして含めることで、そのデータを見れば次にどのエンドポイントにアクセスすれば良いかがわかるような設計

第3章 レスポンスデータの設計
JSONをデフォルトとして対応し、必要があればXMLに対応する、というのが最も現実に即している。
クライアントにどのように取得したい形式を指定させるべきか
・クエリパラメータを使う方法
https://api.example.com/v1/users?format=xml
・拡張子を使う方法
https://api.example.com/v1/users.json
・リクエストヘッダでメディアタイプを指定する方法
GET /v1/users
Host: api.example.com
Accept: application/json
レスポンスデータを決定する際に考えるべきことは、APIのアクセス回数がなるべく減るようにすること
APIのアクセス回数が増えると利用者にとって煩雑な上に、HTTPのオーバーヘッドも上がってアプリケーションの速度が低下する。
ただ、レスポンスのデータサイズが大きいのも問題である。
解決策として、取得する項目を利用者が選択可能にする。
クエリパラメータを使って、ユーザー情報のうち名前と年齢を取得したいと指定する。
http://api.example.com/v1/users/12345?fields=name,age
エンベロープとは、すべてのデータ(レスポンスやリクエスト)を同じ構造でくるむこと。
エンベロープは実際のデータ以外に返したいメタ情報も含まれていて便利そうだが、実施には冗長な表現であるためやるべきではない。
なぜならHTTPがエンベロープの役割を持っており、ヘッダにさまざまなデータを入れることができるからです。
{
"header": {
"status": "success",
"errorCode": 0,
},
"response": {
... 実際のデータ ...
}
}
Google の JSON Style Guideによると、「なるべくフラットにしたほうが良いけど、階層構造を持った方がわかりやすい場合もあるよね」というような曖昧な表記になっている。
送信者や受信者のように同じユーザーという構造を表す場合は階層構造で表現した方が分かりやすい
階層的に表す場合
{
"id": 3342124,
"message": "Hi!"
"sender": {
"id": 3456,
"name": "Taro Yamada"
},
"receiver": {
"id": 12912,
"name": "Kenji Suzuki"
}
}
フラットに表す場合
{
"id": 3342124,
"message": "Hi!"
"sender_id": 3456,
"sender_name": "Taro Yamada"
"receiver_id": 12912,
"receiver_name": "Kenji Suzuki"
}
オブジェクトで包んで配列データを渡した方が良い
・レスポンスデータが何を示しているものかがわかりやすくなる
・レスポンスデータをオブジェクトに統一することができる
・セキュリティ上のリスクを避けることができる
(トップレベルが配列であるJSONは、JSONインジェクションという脆弱性に対するリスクが大きくなるという問題を抱えている)
{
"friends": [
{
"id": 234342,
"name": "Taro Tanaka",
"profileIcon": "http://image.example.com/profile/234342.png",
},
{
"id": 93734,
"name": "Hanako Yamada",
"profileIcon": "http://image.example.com/profile/93734.png",
},
]
}
日付のフォーマット
基本的にはRFC 3339を使う方が良い
理由としては数あるこれまでの日時を表すフォーマットの問題を解決し、読みやすくて使いやすいものを目指してインターネット上で用いる標準形式として決められたものだから
RFC 822 Sun, 06 Nov 1994 08:49:37 GMT
RFC 850 Sunday, 06-Nov-94 08:49:37 GMT
ANSICのasctime()形式 Sun Nov 6 08:49:37 1994
RFC 3339 2015-10-12T11:30:22+09:00
Unix タイムスタンプ(epoch秒) 1396821803
エラーの詳細をクライアントに返す
ステータスコードでエラーのざっくりとした理由が分かるが、詳細は分からない
エラーの内容を返す方法は大きく分けて2つある。
基本的にはレスポンスボディにデータを入れる方法を使っている
HTTPのレスポンスヘッダに入れて返す方法
X-MYNAME-ERROR-CODE: 2013
X-MYNAME-ERROR-MESSAGE: Bad authentication token
X-MYNAME-ERROR-INFO: http://docs.example.com/api/v1/authentication
レスポンスボディで返す方法
{
"error": {
"code": 2013,
"message": "Bad authentication token",
"info": "http://docs.example.com/api/v1/authentication"
}
}
エラー詳細情報には何を入れるべきか
{
error: {
"developerMessage": "... 開発者向けエラーメッセージ ...",
"userMessage": "... ユーザー向けエラーメッセージ ...",
"code": 2013,
"info": "http://docs.example.com/api/v1/authentication"
}
}
APIのメンテナンスをしなければならない場合、ステータスコード503を返し、現在サービスが停止していることを伝える必要がある
Retry-AfterというHTTPヘッダを使っていつメンテナンスが終わるのかを示す必要がある

第4章 HTTPの仕様を最大限利用する
ステータスコード一覧
200 OK リクエスト成功
201 Created リクエストが成功し、新しいリソースが作られた
202 Accepted リクエストは成功した
204 No Content コンテンツなし
300 Multiple Choicees 複数のリソースが存在する
301 Moved Permanently リソースは恒久的に移動した
302 Found リクエストしたリソースは一時的に移動している
303 See Other 他を参照
304 Not Modified 前回から更新されていない
307 Temporary Redirect リクエストしたリソースは一時的に移動している
400 Bad Request リクエストが正しくない
401 Unauthorized 認証が必要
403 Forbidden アクセスが禁止されている
404 Not Found 指定したリソースが見つからない
405 Method Not Allowed 指定されたメソッドは使うことができない
406 Not Acceptable Accept関連のヘッダに受理できない内容が含まれている
408 Request Timeout リクエストが時間以内に完了しなかった
409 Conflict リソースが矛盾した
410 Gone 指定したリソースは消失した
413 Request Entity Too Large リクエストボディが大きすぎる
414 Request-URI Too Long リクエストされたURIが長すぎる
415 Unsupported Media Type サポートしていないメディアタイプが指定された
429 Too Many Requests リクエスト回数が多すぎる
500 Internal Server Error サーバ側でエラーが発生した
503 Service Unavailable サーバが一時的に停止している
リダイレクトの場合はLocationというレスポンスヘッダにリダイレクト先の新しいURIが含まれる
HTTP/1.1 302 Found
Date: Sat, 23 Nov 2013 12:25:37 GMT
Content-Type: text/plain
Content-Length: 41
Connection: keep-alive
Location: http://example.com
400(Bad Request)は他の400番台のエラーでは表すことができないエラーのこと
401は認証(Authentication)のエラー
403は認可(Authorization)のエラー
認証とはアクセスしてきたのが誰であるかを識別すること(あなたが誰だかわからないよ)
認可とは特定のユーザーに対してある操作の権限を許可すること(あなたが誰だかは分かったけどこの操作はあなたには認可されていないよ)
500(Internal Server Error)ですが、サーバ側のコードにバグがあってエラーを吐いて処理が停止してしまった場合などに発生
500番台のエラーはログをきちんと監視して管理者に通知がいくように設定し、発生時には再発を防止するようにしておくのが良い
503(Service Unavailable)サーバが一時的に利用できない状態になっていることを示す
メンテナンスのためにサービスを止めるケース
キャッシュのメリット
・サーバへの通信を減らすことができるため、ユーザーの体感速度を上げることができる
・ネットワーク接続が切れた状態でもある程度サービスを継続できる
・サーバへの通信回数、転送量を減らすことでユーザーの通信コストを下げることができる
・サーバへのアクセス回数が減ることで、サーバの維持費用を抑えることができる
キャッシュのディレクティブとその意味
public キャッシュはプロキシにおいてユーザが異なっても共有することができる
private キャッシュはユーザごとに異なる必要がある
no-cache キャッシュしたデータは検証モデルによって確認が必要
no-store キャッシュしてはならない
no-transform プロキシサーバはコンテンツのメディアタイプやそのほか内容を変更してはならない
must-revalidate いかなる場合もオリジナルのサーバへの再検証が必要
proxy-revalidate プロキシサーバはオリジナルのサーバへの再検証が必要
max-age データが新鮮である期間を示す
s-maxage max-ageと同様だが中継するサーバでのみ利用される

第5章 設計変更をしやすいWeb APIを作る
一度公開したWeb APIの仕様を変更するのはいずれにせよ問題が発生する危険性があるが、ではどうすれば良いか?
APIをバージョンで管理する
最も良いと思われる方法は、一度公開したAPIをできる限り変更しないこと
つまり、古い形式でアクセスしてきているクライアントに対してはそれまでと変わらないデータを送り、新しい形式でのアクセスの場合は新しい形式のデータを返す
複数のバージョンのAPIを提供するというわけ
具体例①
全く異なるURIでAPIを公開する方法
この方法はイけてない
古いURI
http://api.example.com/users/123
新しいURI
http://newapi.example.com/users/123
具体例②
ソフトウェアと同様にバージョン番号を振っていく
http://api.twitter.com/1/statusers/user_timeline.json
バージョニング
1.2.3 それぞれの数値はメジャー、マイナー、パッチと呼ばれる
・パッチバージョンはソフトウェアのAPIに変更がないバグ修正などを行なった時に増える
・マイナーバージョンは後方互換性のある機能変更、あるいは特定の機能が今後廃止されることが決まった場合に増える
・メジャーバージョンは後方互換性のない変更が行われた際に増える
具体例③
バージョンをクエリ文字列に入れる
http://api-public.netflix.com/catalog/titles/series/70023522?v=1.5
具体例④
メディアタイプでバージョンを指定する
Accept: application/vnd.example.v2+json
基本的にはURIのパスにバージョンを入れる方法がよく使われている。セマンティックバージョニングのメジャーバージョンを使うものです。
147

第6章 堅牢なWeb APIを作る
安全性と安定性の2つの面から、堅牢なWeb APIを作るための方法を考えていく
どんなセキュリティの問題があるか?
・サーバとクライアントの間での情報の不正入手
例:同じWifiに繋いでいる人の通信を盗み見ることができる(パケットスニッフィング)
解決策:HTTPSによるHTTP通信の暗号化
理由:HTTPSを使っていれば、通信の盗聴やセッションハイジャックなどは不可能になるため
短所:HTTPと比べてハンドシェイクに時間がかかるため、アクセス速度が遅くなるという問題はある
・サーバの脆弱性による情報の不正入手や改ざん
・ブラウザからのアクセスを想定している API における問題
例:XSS
{"data": "<script>alert('xss');</script>"}
Content-Typeの値がtext/htmlだった場合、このURIに直接ブラウザでアクセスすると、このデータはHTMLとして解釈されて、SCRIPT要素の中に記述されているJavaScriptが実行される
解決策①:Content-Typeにapplication/jsonを返すこと
問題点:Content Snifferingという機能がある。サーバ側で指定したContent-Typeを返していても、ブラウザ側でその間違いに影響されることなく、きちんとコンテンツを表示するために導入されたもの
その問題点の解決策:X-Content-Type-Options: nosniff(レスポンスヘッダ)→ Content-Typeで指定されたメディアタイプとして解釈されるようになる
解決策②:JSON文字列のエスケープ
例:XSRF
ユーザが悪意のあるページにアクセスした際に、その中に埋め込まれたリンクを経由して、全く別のサイトへのリクエストが行われること
解決策①:サーバ側のデータが変化するようなアクセスに関しては、GETメソッドを利用せずにPOSTやPUT、DELETEを用いること
解決策②:XSRFトークンを使う(そのサイトが発行したワンタイムトークン、あるいは少なくともセッションごとにユニークなトークンを埋め込んでいき、そのトークンがないアクセスは拒否する)
例:JSONハイジャック
APIからJSONで送られてくる情報を悪意ある第三者が盗み取ること
解決策
:JSON を SCRIPT 要素では読み込めないようにする
:JSON をブラウザが必ず JSON と認識するようにする
:JSON を JavaScript として解釈不可能、あるいは実行時にデータを読み込めないようにす
る

XSS(クロスサイトスクリプティング)
① 攻撃者が立ち上げたサーバーで悪意あるコードを含むリンクを生成
② 攻撃者が設定した悪意あるコードを含むリンクを通じて、ユーザがページを表示
③ XSSによって挿入された悪意あるコードが実行される(例えば、セッション情報を取得するなど)
④ 攻撃者がユーザのセッション情報を取得し、不正に脆弱性のあるサイトにそのユーザとしてログインする

クロスサイトリクエストフォージェリ

Session と Cookieについて
・ユーザー一覧画面のHTMLをGETでリクエストする
・その際にSessionにsessionのIDとユーザ情報が格納される
・レスポンスを返すが、そのレスポンスヘッダーにはSet-cookieでsession Idが格納されている
・そのsession idをcookieに保存する
・A画面のHTMLをGETでリクエストするが、その際はsession idをサーバーに渡す
・サーバーはsession idを元にSESSIONからidを検索し、ユーザーの情報を取得する
・真っ白なブラウザから入力画面を受け取るリクエストを送信
・Sessionにユーザー情報と紐づいたsession idを格納する
・レスポンスに入力画面のhtmlが渡され、ヘッダーにはsession idが格納されている
・入力を行い、送信ボタンを押下すると、確認画面を受け取るリクエストを送信
・リクエストに入っているsession idを元にSessionにあるsession idを探す
・そのsession idに紐付けて、入力された名前(小林)をセットする
・レスポンスに確認画面のhtmlが渡される
・送信ボタンを押下すると、Sessionに格納された名前(小林)をDBにセットする
・その後に完了画面をhtmlでレスポンスとして渡される。
・session idによって、同じユーザがリクエストを送っていることがわかる

リダイレクトについて
・ブラウザから ログイン画面を取得する リクエストを送る
・ログイン画面が表示され、ユーザーIDとパスワードを入力し、送信ボタンを押下する
・バリデーションで失敗した場合、SESSION にユーザの情報とSessionIdとログイン失敗情報を格納する
・空のHTMLを返し、レスポンスヘッダーにはログイン画面に再度行け!という情報が格納されている(302)
・リダイレクト先のログイン画面を取得する GET リクエストを送り、ログイン画面に遷移する
・その際にNGでしたと表示される

Validation Model(検証モデル)
検証モデルは今持っているキャッシュが有効かどうかをサーバに問い合わせる。
一度、WebサイトAのhtmlを取得する。その際にキャッシュでhtmlを持っておく。
もう一度、WebサイトAのhtmlを取得するリクエストを送る。
その際に、If-Modified-Sinceにキャッシュで持っているhtmlがいつ変更されたのかを指定して、リクエストを送る。
レスポンスのStatus Codeとして304のNot Modifiedが返されたので、キャッシュされたhtmlが最新のものであるとわかったため、キャッシュされたhtmlを表示させる。
レスポンスにはEtag(WebサイトAのhtmlを一意に指定するためのtag)とLast-Modified(最新のリソース更新日時)を返す。

OAuthの仕組み

JWTとは
JWTとは、JSON Web Tokenの略称で、JSONの形をした認証情報
電子署名より、改ざんの検知が可能
認証用のトークンとして利用される
構成
ヘッダ、ペイロード、署名の3つから構成されている
[ヘッダ].[ペイロード].[署名]
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
t42p4AHef69Tyyi88U6+p0utZYYrg7mmCGhoAd7Zffs
作り方
【ヘッダ】
アルゴリズムとTokenのタイプをヘッダに設定する
HS256は、256ビットのハッシュ値を生成する関数
{
"alg": "HS256",
"typ": "JWT"
}
上記ヘッダをBase64でエンコード
echo -n '{"alg":"HS256","typ":"JWT"}' | base64
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
【ペイロード】(データの本体の意)
issued at: JWTを発行した時刻
subject: JWTの主語となる主体の識別子
{
"sub": "1234567890",
"iat": 1516239022
}
上記ペイロードをBase64でエンコード
echo -n '{"sub":"1234567890","iat":1516239022}' | base64
eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyfQ
ヘッダとペイロードをドットで結合し、署名なしTokenを生成
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyfQ
署名なしTokenに対し、秘密鍵とHMAC-SHA256を用いて署名を生成
echo -n 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyfQ' |
openssl dgst -binary -sha256 -hmac 'secret' |
base64
t42p4AHef69Tyyi88U6+p0utZYYrg7mmCGhoAd7Zffs
署名なしTokenと署名をドットで結合。下記がJWTになる
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
t42p4AHef69Tyyi88U6+p0utZYYrg7mmCGhoAd7Zffs

JWTの利用

SQL 第2版: ゼロからはじめるデータベース操作