【PHP】PHPフレームワーク「Flow」を試してみる～認可編～

# 初めに
前回は[こちら](https://qiita.com/nnhkrnk/items/2ab36bd082385f62cd61)の記事で、Flowにおける認証処理（Authentication）について書きました。
今回はFlowで認可処理（Authorization）を実装してみましょう。

# 注意
:::note warn
この記事は[前回の記事](https://qiita.com/nnhkrnk/items/2ab36bd082385f62cd61)の続きになっています。
まだご覧になってない方はそちらからご覧ください。
:::


# 実際に作ってみる
早速作ってみましょう。
前回はログインしたらTOP画面に遷移するという処理を実装しましたが、ログインしてなくても遷移が可能になっていました。
今回は、**TOP画面をログイン状態でないと開けない**という設定を追加してみます。

プロジェクト構成は以下です。

```
Packages/
  ├ Application/
  |    └ Neos.Welcome/
  |         ├ Classes/
  |         |    └ Controller/
  |         |         ├ AccountController.php
  |         |         ├ LoginController.php
  |         |         └ TopController.php
  |         |
  |         ├ Configration/
  |         |    ├ Policy.yaml
  |         |    └ Settings.yaml
  |         |
  |         └ Resources/
  |              └ Private/
  |                   └ Templates/
  |                        ├ Login/
  |                        |   └ index.html
  |                        └ Top/
  |                            └ index.html
  |
  ├ Framework/
  └ Libraries/
```


## Policy.yaml
前回作成したPolicy.yamlに記載を追加します。

```Policy.yaml
privilegeTargets: 
  'Neos\Flow\Security\Authorization\Privilege\Method\MethodPrivilege':
    'Neos.Welcome:Restricted':
      label: 'Top level'
      matcher: 'method(Neos\Welcome\Controller\TopController->indexAction())'

roles:
  'Neos.Welcome:Everybody':
    # abstract: true
    label: 'Magic "everybody" role'
    description: 'This magic role is always active, even if no account is authenticated'
    privileges:
      -
        privilegeTarget: 'Neos.Welcome:Restricted'
        permission: GRANT
```

### ポイント1：privilegeTargetsを記載
Policy.yamlに`PlivirageTargets`の定義を記載します。
重要な用語について触れながら解説していきます。

#### ①PlivirageTargets
`PlivirageTargets`とは、**特定のリソースや処理に対するアクセス権を定義するためのもの**です。`PlivirageTargets`に保護したいリソースを記載し、後述するroleと紐づけることで、**特定のroleでしか開けないという設定を付与する**ことができます。

#### ②MethodPrivilege
`MethodPrivilege`はFlowが提供しているクラスで、これを指定することでにアクセス権をメソッドごと設定することができます。
`Privirage`にも種類があり、`MethodPrivilege`以外にも`Entity`や`Parameter`を指定する`Privirage`などがあります。また、`PrivirageInterface`を継承することで、独自の`Privirage`も作成可能です。

今回は、TOP画面を開くActionメソッドを設定し、`Neos.Welcome:Restricted`という名前で定義しました。

### ポイント2：roleにprivilegeTargetを紐づける
先ほど定義した`Neos.Welcome:Restricted`とroleを紐づけます。
`privilegeTarget`に定義名を記載し、`Permission`を`GRANT`に設定すればOKです。


## 動作確認


`http://localhost:8081/neos.welcome/top/index`をブラウザ上で打ち込み、ログイン画面に遷移するか見てみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430841/3de4878d-d278-4d8e-e561-46023ae565bd.png)


ちゃんとログイン画面に遷移してくれました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430841/476724fd-1496-f213-17cb-3a1ad79ac2f1.png)


続いてログインしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430841/fbf04632-43f7-abe7-c9d9-8139bdd5ff11.png)

ログイン後はちゃんとTOP画面に遷移してくれました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430841/035494d9-a850-74d0-ca0a-1b468306d27e.png)

この状態でTOP画面のURLを直指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430841/6894a126-8cbf-56e0-fccd-884a1687d112.png)

問題なくTOP画面開いてくれました。いい感じですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430841/b2d95f6d-535d-d984-a4ab-b42d6e777f62.png)


# 余談：ロールに`Neos.Flow:Everybody`を指定したPrivirageは、未ログイン状態でアクセスすることができる
`Neos.Flow:Everybody`はFlowが用意しているroleで、未ログイン状態のユーザを指します。
そのため、このroleにPrivirageを紐づけた場合、未ログイン状態でアクセスできるリソースと定義することができます。

ログイン画面やパスワード設定画面などはこのroleで設定しておけば、未ログイン状態で開くことができますね。

```yaml:Policy.yaml
privilegeTargets: 
  'Neos\Flow\Security\Authorization\Privilege\Method\MethodPrivilege':
    'Neos.Welcome:Top.index':
      label: 'Top level'
      matcher: 'method(Neos\Welcome\Controller\TopController->indexAction())'

roles:
  'Neos.Flow:Everybody':
    # abstract: true
    label: 'Magic "everybody" role'
    description: 'This magic role is always active, even if no account is authenticated'
    privileges:
      -
        privilegeTarget: 'Neos.Welcome:Top.index'
        permission: GRANT
```

# 終わりに
今回は認可処理について書きました。
ログインって難しいイメージがあったんですが、前回の認証といい今回の認可といい、思いのほか簡単に実装できて面白いです。
認証系はいろいろ深堀が面白そうなので、SSOや二段階認証などの実装も今度試してみようと思います。

ここまで読んでくださりありがとうございました！