bff

フルスタックエンジニアを目指して学んだことなどを記録しています

MacのF12キーでDeveloper Toolsを起動する方法

Windowsでの開発に慣れているとMacでもF12で開発者ツール(Developer Tools)を起動したい衝動に駆られます。

以前設定をしたのですが、Mission Control周りを触った時に誤って設定が解除されてしまったので、備忘のために方法を残しておきます。

ちなみにこの設定を入れる前は、F12を押すとMission Controlのダッシュボードが開くようになってしまっていました。誰に需要があるのか謎の画面ですが、便利に使っている人がいたら教えて欲しいです。

  1. システム環境設定 > キーボードの設定を開く
  2. ショートカットキーのタブに移動する
  3. Mission Controlをリストから選択し、"Dashboardを表示”のチェックを外す
  4. アプリケーションを選択し、”+”を押す
  5. Google Chrome.appを選び、メニュータイトルに"デベロッパー ツール”と入れる
  6. キーボードショートカットの入力欄をクリックし、F12キーを押す

なお、5.のメニュータイトルの文字列を見て完全一致のものを探しているようですので、入力ミスにはご注意ください。 自分の環境では3まで実施すればF12で開くようになったので、4以降の手順はいらないかもしれません。(このときChromeでメニューバーのショートカットキーを確認すると、Command + Option + I になっていました。)

OAuth 2.0と認証について

OAuth 2.0では一部認証について語っている部分があります。 上記フローの理解の一助になるよう、認証の位置付けについて簡単にまとめました。

認証の種類

OAuth 2.0ではサービス側が認証すべきものとして、a. アプリ、b. ユーザがあります。

  1. アプリの認証は、不適切なアプリがサービスのデータを利用しないようにコントロールをする必要があるために行うものです。 例としては、GoogleFacebookAPIを利用する時に取得が必要なclient_id, client_secretが該当します。 認可サーバの提供側としては、これらでアプリを認証することで、悪意を持ったアプリによるアクセスを防ぐ必要があります。

  2. ユーザの認証は、サービス内にユーザが保有しているデータを見せてよいのかコントロールする必要があるために行うものです。 例としては、GoogleFacebookと連携する際に、(これらのサービスにユーザがまだログインしていない場合は)ログインを求められることが挙げられます。

OAuth 2.0における4つの承認フロー

OAuth 2.0に関する実装を行う機会があったので、個人的に勉強した内容をまとめました。 OAuth 2.0と一口に言っても、4つのフローが規定されており、ユースケースに応じて適切なものを使う必要があるので、ざっくりとその概要を理解できるようにまとめました。

OAuth 2.0とは

サービス上で保有しているユーザのデータについて、ユーザが第三者のアプリケーションに対してID・パスワードを渡すことなく連携することができるようにする仕組みです。 GoogleFacebookTwitterで以下のような画面で認証することで、例えばFacebook上のアプリケーションがTwitter上のデータを組み合わせてサービス提供している仕組みというとイメージしやすいと思います。 f:id:tsbkw:20190208234336p:plain

OAuth 2.0の仕様のなかでは一部認証(Authentication:誰なのか)について語っている部分もありますが、あくまでもOAuth 2.0は認可(Authorization:誰に何の権限を与えるか)の仕組みです。

OAuth 2.0の承認フローについて

OAuth 2.0では4つの承認フローが定義されています。フローの特徴とその流れについてまとめています。 ここでの説明では、以下の用語を利用しています。参考までにRFC上の用語を括弧書きしています。 * アプリ(client): OAuth 2.0を利用してサービスを提供するアプリケーション。 * サービス: アプリにデータを提供するサービス。認可サーバとリソースサーバで構成されます。      認可サーバ(authorization server): データをアプリに提供してよいか(認可)を制御するサーバ      リソースサーバ(resource server): 認可サーバの制御に基づき、自身が保有するデータをアプリに提供するサーバ。 * ユーザ(end-user/resource owner): アプリとサービス双方を利用しているユーザ。

1. Authorization Code Grant

(RFC 6749 4.1 Authorization Code Grant)https://tools.ietf.org/html/rfc6749#section-4.1で規定されているフローです。

特徴は、認可コードを一時的に取得し、それを元にアクセス・リフレッシュトークンを取得するところです。

フローは次の通りです。

  1. アプリから外部の認可サーバが提供する認可画面に遷移して、ユーザが認可(権限をアプリに渡してよいかのチェックを、サービスへのログインID・パスワードを入力して実施)を行います。
  2. 認可されると、1. の遷移時にアプリが指定したURIへ認可画面がリダイレクトしてくれるので、アプリはGETパラメータに含まれる認可コードを受け取ります。
  3. この認可コードを用いてアプリは認可サーバへアクセストークン、リフレッシュトークンの値を受け取りに行きます。(リフレッシュトークンはオプションのため、認可サーバによっては返してくれません。)
  4. 受け取ったアクセストークンを用いて、アプリはリソースサーバからデータを取得します。
  5. アクセストークンの期限が切れたらリフレッシュトークンによってアクセストークンを更新する必要があります。

認可のまえに認証を求められることが多く、client_id、client_secretを用いた認証やBasic認証が利用されます。実装の詳細は認可サービス(Google, Facebookなど)のドキュメントを参照してください。認可を利用するアプリ向けにライブラリを提供しておりその利用を推奨しているケースもあります。(例:(Google)https://developers.google.com/api-client-library/では他のAPIと同様にOAuth2向けのライブラリを言語別に提供しています)

なお、スマホアプリの場合は認可コード横取り攻撃(authorization code interception attack)の危険性があるので、PKCE(Proof Key for Code Exchange)による対策が必要です。詳細は以下の記事が詳しいですが、code_challengeのやりとりを上記フローの中に含めるものです。 (PKCE: 認可コード横取り攻撃対策のために OAuth サーバーとクライアントが実装すべきこと)https://qiita.com/TakahikoKawasaki/items/00f333c72ed96c4da659

2. Implicit Grant

(RFC 6749 Implicit Grant)https://tools.ietf.org/html/rfc6749#section-4.2で規定されているフローです。

特徴は、認可コードのやりとりをすることなくアクセストークンを取得できるためフローがシンプルなことと、リフレッシュトークンが発行されないため、有効期限が切れた際は再度アクセストークンの発行が必要になることです。 フローの中でAuthorization Code Grantとの違いを太字にしています。

  1. アプリから外部の認可サーバが提供する認可画面に遷移して、ユーザが認可を行います。
  2. 認可されると、1. の遷移時にアプリが指定したURIへ認可画面がリダイレクトしてくれるので、アプリはGETパラメータに含まれるアクセストークを受け取ります。
  3. 受け取ったアクセストークンを用いて、リソースサーバからデータを取得します。

3. Resource Owner Password Credentials Grant

(RFC 6749 4.3 Resource Owner Password Credentials Grant)https://tools.ietf.org/html/rfc6749#section-4.3で規定されているフローです。

特徴は、1. , 2. のフローではサービス側がユーザに対して認可画面を表示していたのに対し、このフローではサービス側がユーザに認可画面を表示する点です。 そのため、ユーザがサービスで利用しているID、パスワードをアプリ側が知ることができてしまい、アプリ側が信頼できない場合にこのフローを利用するのは危険です。 RFCでも1., 2. のフローが利用できないケースでのみ利用すべきとされています。

  1. アプリが認可画面を表示し、ユーザにサービスへのログインID・パスワードの入力させます。
  2. アプリは1.で受け取ったログインID、パスワードをパラメータに含むPOSTリクエストによって認可サーバへアクセストークンを要求します。
  3. 認可サーバはHTTPレスポンスによってアクセストークンをアプリに返します。(認可サーバによってはオプションでリフレッシュトークンを返します。)
  4. 受け取ったアクセストークンを用いて、アプリはリソースサーバからデータを取得します。

4. Client Credentials Grant

(RFC 6749, 4.4. Client Credentials Grant)https://tools.ietf.org/html/rfc6749#section-4.4で規定されているフローです。

特徴は、ユーザの認証を行わず、client_id、client_secretもしくはBasic認証によるアプリの認証のみが行われる点です。

  1. アプリは認可サーバに対して認証情報を送り、アクセストークンを要求します。
  2. 認可サーバは認証情報を確認し、アクセストークンを発行します。

automatic semicolon insertion(セミコロン自動挿入)の挙動について

Reactを学ぶなかで、セミコロン自動挿入を防ぐためにJSXを括弧()で括ることが推奨されていました。 javascriptセミコロン自動挿入の挙動をあまり知らなかったので調べて見ました。

仕様としては、ECMA Scriptの§11.9.1 Rules of Automatic Semicolon Insertionに纏められています。

  1. 改行もしくは}が文法的に許されていない場所に出てきたときに、その前にセミコロンが挿入される
  2. 入力を読み終わったときに、完全なScript/Moduleとして解析(parse)できない場合は、セミコロンが入力の後ろに挿入される
  3. 読み込んだトークンがRestricted tokenに該当する場合、その前にセミコロンが挿入される。(continue, break, return, throw, yieldの後に改行があった場合、その改行の前にセミコロンが挿入される。postfixオペレータとして++, --が扱われる状況で、++,--の前に改行が入った場合、改行の前にセミコロンが挿入される。)

自分の語学力が拙いせいもあり、いまいち理解しづらいかと思いますが、一定の複雑なルールに基づきセミコロン自動挿入が行われる可能性があるため、気をつけたほうがよいということは理解できました。

もっとわかりやすい解説があれば教えていただけるとありがたいです。

Reactでのpropsの利用法

Reactのチュートリアルをする中で、propsの挙動を理解するために調べました。

propsの使い方

propsはComponent間でのデータの受け渡しに利用されます。 renderの中で受け渡し先のComponent(以下の例ではChild)にPropertyを設定すると、this.propsからアクセスできます。これによりデータの受け渡しが実現できます。

class Parent extends React.Component {
  render() {
    const a = 10;
    const b = 20;
    return <Child p1={a} p2={b}/> // ここでPropertyを設定
  }
}

class Child extends React.Component {
  render() {
    return <div><div>p1:{this.props.p1}</div> // ここでpropからアクセス可能
      <div>p2:{this.props.p2}</div></div>;
  }
}

表示結果 p1:10 p2:20

チュートリアルのコードの中で、最初見たときに理解できなかったのは次のコードでした。 コンポーネントの構造としては、Game > Board > Squareという形で組み立てられています。 挙動としては、SquareをクリックするとGameの中に定義されているhandleClickが呼ばれるというものです。 * コード抜粋1

// Boardコンポーネントの中の処理
renderSquare(i) {
  return <Square
      value={this.props.squares[i]}
      onClick={() => this.props.onClick(i)}
    />;
}
  • コード抜粋2
// GameコンポーネントにおけるBoardの呼び出し処理
<Board
  squares={current.squares}
  onClick={(i) => this.handleClick(i)}
/>

コード抜粋1の部分ではSquareのonClickが呼ばれると、BoardのpropsのonClickが呼ばれるようになっています。 そして、コード抜粋2の部分で、Boardのpropertyとしてthis(ここではGame)のhandleClickが呼ばれるようになっています。

通常は呼び出し元Component(Game)から呼び出し先のComponent(Square)に値を渡すときに使います。 しかし、この例では呼び出し元側でpropsに関数をバインドし、その関数の引数を呼び出し先で設定することで、呼び出し先(Square)の値を呼び出し元(Game)に伝えています。 Reactではこのようにpropsを活用してComponent間のデータ連携を実現するようです。

Maximum update depth exceeded errorの原因と対処法

Reactで開発をしていた際、Maximum update depth exceeded errorが発生したので原因と対処方をまとめておきます。
 

原因

Componentのrenderメソッドの中で、setStateを呼び出していたことが原因。
ReactではsetStateを呼ぶとViewを更新するためにrenderメソッドが呼ばれる。そのため、setState => renderの呼び出し => 再びsetStateの呼び出し => 以下繰り返しとなり、無限ループとなる可能性がある。
これを避けるためにReactではrender中のsetStateを検知し、エラーとするようになっている。
 

対処法

render内のsetStateを削除する。
自分の場合、以下のようにonClickでsetStateを呼び出してしまっていた。
someparams = some-processes;
return (
    <button onClick={this.setState(someparams)}></button>
);
ここでは、onClick時にsetStateを呼び出すべきなので、以下のようにonClick時に呼び出すべき関数を定義するのが正しい。
someparams = some-processes;
return (
    <button onClick={someparams => this.setState(someparams)}></button>
);
 

カリー化とは

カリー化についての理解が浅かったため、調べてまとめました。

カリー化とは

複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること

要は以下のようなoriginalからcurriedへの変更を指します。

const original = (a, b) => {
return a + b;
};
 
const curried = (a) => {
consut num [];
return (b) => a + b;
};
 
original(1, 2); // 3
curried(1)(2); //3

メリット?

カリー化によって、部分適用(片方の引数を固定し、もう片方の引数のみをとる関数を作成すること)が簡単にできるようになります。

// 例えば、毎回片方の引数は1の場合、元の処理だと都度以下のように記載します。
original(1, 1); // 2
original(1, 2); // 3
original(1, 100); // 101
 
// 一方で、カリー化を使えば片方の引数を固定した関数が簡単に作れます。
const partial = curried(1);
partial(1); // 2
partial(2); // 3
partial(100); // 101

といっても、あまり趣味の範囲な気がしますし、読みづらいと感じる人も多いのではないでしょうか。
Haskellのような関数型言語であれば、言語自体がカリー化をサポートしておりメリットが享受できるらしいですが、JavaScriptではカリー化を使う意味は薄いと感じました。

何かいいユースケースがあればコメントに記載ください。

%u30AB%u30EA%u30FC%u5316%u95A2%u6570%u306B%u3064%u3044%u3066%u306E%u7406%u89E3%u304C%u6D45%u304B%u3063%u305F%u305F%u3081%u3001%u8ABF%u3079%u3066%u307E%u3068%u3081%u307E%u3057%u305F%u3002%0A%0A%23%23%23%20%u30AB%u30EA%u30FC%u5316%u3068%u306F%0A%3E%u8907%u6570%u306E%u5F15%u6570%u3092%u3068%u308B%u95A2%u6570%u3092%u3001%u5F15%u6570%u304C%u300C%u3082%u3068%u306E%u95A2%u6570%u306E%u6700%u521D%u306E%u5F15%u6570%u300D%u3067%u623B%u308A%u5024%u304C%u300C%u3082%u3068%u306E%u95A2%u6570%u306E%u6B8B%u308A%u306E%u5F15%u6570%u3092%u53D6%u308A%u7D50%u679C%u3092%u8FD4%u3059%u95A2%u6570%u300D%u3067%u3042%u308B%u3088%u3046%u306A%u95A2%u6570%u306B%u3059%u308B%u3053%u3068%0A%0A%u8981%u306F%u4EE5%u4E0B%u306E%u3088%u3046%u306Aoriginal%u304B%u3089curried%u3078%u306E%u5909%u66F4%u3092%u6307%u3057%u307E%u3059%u3002%0A%60%60%60%0Aconst%20original%20%3D%20%28a%2C%20b%29%20%3D%3E%20%7B%0A%09return%20a%20+%20b%3B%0A%7D%3B%0A%0Aconst%20curried%20%3D%20%28a%29%20%3D%3E%20%7B%0A%20%20%20%20consut%20num%20%5B%5D%3B%0A%09return%20%28b%29%20%3D%3E%20a%20+%20b%3B%0A%7D%3B%0A%0Aoriginal%281%2C%202%29%3B%20//%203%0Acurried%281%29%282%29%3B%20//3%20%0A%60%60%60%0A%0A%23%23%23%20%u30E1%u30EA%u30C3%u30C8%3F%0A%u30AB%u30EA%u30FC%u5316%u306B%u3088%u3063%u3066%u3001%u90E8%u5206%u9069%u7528%28%u7247%u65B9%u306E%u5F15%u6570%u3092%u56FA%u5B9A%u3057%u3001%u3082%u3046%u7247%u65B9%u306E%u5F15%u6570%u306E%u307F%u3092%u3068%u308B%u95A2%u6570%u3092%u4F5C%u6210%u3059%u308B%u3053%u3068%29%u304C%u7C21%u5358%u306B%u3067%u304D%u308B%u3088%u3046%u306B%u306A%u308A%u307E%u3059%u3002%0A%60%60%60%0A//%20%u4F8B%u3048%u3070%u3001%u6BCE%u56DE%u7247%u65B9%u306E%u5F15%u6570%u306F1%u306E%u5834%u5408%u3001%u5143%u306E%u51E6%u7406%u3060%u3068%u90FD%u5EA6%u4EE5%u4E0B%u306E%u3088%u3046%u306B%u8A18%u8F09%u3057%u307E%u3059%u3002%0Aoriginal%281%2C%201%29%3B%20//%202%0Aoriginal%281%2C%202%29%3B%20//%203%0Aoriginal%281%2C%20100%29%3B%20//%20101%0A%0A//%20%u4E00%u65B9%u3067%u3001%u30AB%u30EA%u30FC%u5316%u3092%u4F7F%u3048%u3070%u7247%u65B9%u306E%u5F15%u6570%u3092%u56FA%u5B9A%u3057%u305F%u95A2%u6570%u304C%u7C21%u5358%u306B%u4F5C%u308C%u307E%u3059%u3002%0Aconst%20partial%20%3D%20curried%281%29%3B%0Apartial%281%29%3B%20//%202%0Apartial%282%29%3B%20//%203%0Apartial%28100%29%3B%20//%20101%0A%60%60%60%0A%0A%u3068%u3044%u3063%u3066%u3082%u3001%u3042%u307E%u308A%u8DA3%u5473%u306E%u7BC4%u56F2%u306A%u6C17%u304C%u3057%u307E%u3059%u3057%u3001%u8AAD%u307F%u3065%u3089%u3044%u3068%u611F%u3058%u308B%u4EBA%u3082%u591A%u3044%u306E%u3067%u306F%u306A%u3044%u3067%u3057%u3087%u3046%u304B%u3002%0AHaskell%u306E%u3088%u3046%u306A%u95A2%u6570%u578B%u8A00%u8A9E%u3067%u3042%u308C%u3070%u3001%u8A00%u8A9E%u81EA%u4F53%u304C%u30AB%u30EA%u30FC%u5316%u3092%u30B5%u30DD%u30FC%u30C8%u3057%u3066%u304A%u308A%u30E1%u30EA%u30C3%u30C8%u304C%u4EAB%u53D7%u3067%u304D%u308B%u3089%u3057%u3044%u3067%u3059%u304C%u3001JavaScript%u3067%u306F%u30AB%u30EA%u30FC%u5316%u3092%u4F7F%u3046%u610F%u5473%u306F%u8584%u3044%u3068%u611F%u3058%u307E%u3057%u305F%u3002%0A%0A%u4F55%u304B%u3044%u3044%u30E6%u30FC%u30B9%u30B1%u30FC%u30B9%u304C%u3042%u308C%u3070%u30B3%u30E1%u30F3%u30C8%u306B%u8A18%u8F09%u304F%u3060%u3055%u3044%u3002