ApacheShiro使ってみた(遠い過去)

# 導入
こんにちは。元バックエンドエンジニアのYamaです。
今回は過去のプロジェクトで触ったApacheShiroの概要について記事にしました。

# Apache Shiroとは

Apache Shiroは、Javaアプリケーション向けの強力で柔軟なセキュリティフレームワークです。
https://shiro.apache.org/

> **Apache Shiro™** is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.

認証、認可、暗号化、およびセッション管理を簡単に実装できるように設計されています。
Shiroは、Webアプリケーションだけでなく、デスクトップアプリケーションやクラウドサービスなどの多様な環境で利用可能です。


# ShiroFilter

Apache Shiroには、ShiroFilterという機能が備わっています。
これは、Javaベースのアプリケーションでセキュリティを実現するための重要なコンポーネントで様々な役割を担います。
その役割を以下に示します。

1. **リクエストの認証・認可**
    - 受信したHTTPリクエストに対してユーザーの認証と認可を実行します。つまり、リクエスト者が`誰であるかの確認`と`特定のリソースやアクションへのアクセス権限の確認`を行なってくれます。
        - 認証に失敗した場合、ユーザーはログインページなどの指定されたページにリダイレクトされます。
        - 認可に失敗した場合、アクセス拒否のエラーページが表示されるか、カスタムエラーハンドリングを行うことが可能です。
    　
2. **セッション管理**
    - ShiroFilterは、ユーザーセッションの作成、管理、および無効化を行います。これには、ユーザーがログインした後のセッション維持や、タイムアウトによるセッションの無効化が含まれます。
      　
3. **クッキーの管理**
    - ユーザーの認証情報をクッキーに保存し、それを使用して再認証を行うことができます。これにより、ユーザーがログイン状態を維持できるようになります。
      　
4. **URLパターンによるフィルタリング**
    - ShiroFilterは、特定のURLパターンに基づいて`セキュリティルール`を適用します。
	    - 例) 特定のパスに対してのみ認証や認可を要求する。
    - これにより、アプリケーションの異なる部分に異なるセキュリティポリシーを適用することが可能です。
      　
5. **カスタムフィルタ**
    - カスタムフィルタを統合して、認証や認可以外のセキュリティ関連のロジック（例えば、ログ記録、リクエストの修正など）を実装できます。
　
## 具体的な動作の流れ

1. **リクエスト受信**：ユーザーがアプリケーションに対してHTTPリクエストを送信します。
2. **ShiroFilterの介入**：ShiroFilterがリクエストを受け取り、フィルタチェーンを開始します。
3. **認証の実施**：リクエストが認証されたユーザーからのものかどうかを確認します。
	- 認証されていない場合、ログインページにリダイレクト。
4. **認可の確認**：ユーザーがリクエストされたリソースまたはアクションにアクセスする権限があるかを確認します。
	- 権限がない場合は、アクセス拒否のエラーページを表示。
5. **リクエストの処理**：リクエストは次のフィルタまたはターゲットリソースに渡されます。
6. **レスポンスの生成**：ターゲットリソースがレスポンスを生成し、ShiroFilterを通じてクライアントに返されます。

このように、ShiroFilterは、アプリケーションのセキュリティを確保するための中心的な役割を果たします。

## ShiroFilterの設定

ShiroFilterは、Map形式で設定されます。
Keyにはフィルタを適用するURLパターンを、Valueには適用するフィルタを格納します。
以下の場合、`/login/**`にマッチする全てのURLパターンに対して`anon`というフィルタが付与されます。

```java
filterMap.put("/login/**", "anon");
```

### 主なフィルタタイプ

#### **anon**
- **用途**：`anon`は「anonymous」を意味します。このフィルタは、ログインページや公開リソースなど、認証が不要なページに対して使用されます。
- **説明**：このフィルタが適用されたURLにアクセスする際、Shiroは認証や認可のチェックを行いません。そのため、どのユーザーでも（認証されていなくても）アクセスが可能です。
    
```java
filterMap.put("/login/**", "anon");
```

####  **authc**    
- **用途**：認証が必要なページに適用します。
- **説明**：認証されていないユーザーがアクセスすると、ログインページにリダイレクトされます。
    
```java
filterMap.put("/user/**", "authc");
```
  
#### **authcBasic**    
- **用途**：HTTPベーシック認証を使用するページに適用します。
- **説明**：HTTPベーシック認証を用いて認証を行います。
    
```java
filterMap.put("/api/**", "authcBasic");
```
    
#### **user**    
- **用途**：記憶されたユーザーまたは認証されたユーザーに適用します。
- **説明**：以前ログインしたことがあり、記憶されているユーザーもアクセス可能です。

```java
filterMap.put("/functions/**", "user");
```
    
#### **logout**
- **用途**：ログアウト処理に適用します。
- **説明**：ログアウトリクエストを処理し、セッションを無効化します。

```java
filterMap.put("/logout", "logout");
```
   
#### **noSessionCreation**  
- **用途**：セッションを作成しないページに適用します。
- **説明**：このフィルタが適用されたURLにアクセスしても、新しいセッションは作成されません。
    
```java
filterMap.put("/api/**", "noSessionCreation");
```

このように、Shiroのフィルタを使って、アプリケーションの異なる部分に対して適切なセキュリティルールを適用することができます。

### フィルタのカスタマイズ

必要に応じてカスタムフィルタを作成し、フィルタチェーンに追加することができます。例えば、特定のロジックを実行するカスタム認証フィルタを作成する場合です。

```java
public class CustomAuthenticationFilter extends FormAuthenticationFilter {
	// カスタムロジックをここに追加 
}
```

```java
Map<String, Filter> filters = new HashMap<>();
filters.put("customAuthc", new CustomAuthenticationFilter()); 
shiroFilter.setFilters(filters);
filterMap.put("/custom/**", "customAuthc");
```

# 終わりに
今回は懐かしのApacheShiroを思い出しながら記事にしてみました。
風変わりなプロジェクトで関わる方がいらっしゃったら、参考になったらと思います。