Upgrade to Pro — share decks privately, control downloads, hide ads and more …

B2B SaaSでSpringSecurityによる Roleを用いたユーザー権限設定の 実装について

Rakus_Dev
November 11, 2023

B2B SaaSでSpringSecurityによる Roleを用いたユーザー権限設定の 実装について

Rakus_Dev

November 11, 2023
Tweet

More Decks by Rakus_Dev

Other Decks in Programming

Transcript

  1. © RAKUS Co., Ltd.
    B2B SaaSでSpringSecurityによる
    Roleを用いたユーザー権限設定の
    実装について
    JJUG CCC 2023 Fall
    株式会社ラクス
    開発統括部
    HUYNH PHUONG(フィン フォン)
    2023/11/11
    1

    View full-size slide

  2. © RAKUS Co., Ltd. 2
    自己紹介
    HUYNH PHUONG(フィン フォン)
    ・株式会社ラクス 開発統括部
    ・バックエンド エンジニア
    ・担当サービス:楽楽電子保存
    自己紹介

    View full-size slide

  3. © RAKUS Co., Ltd. 3
    本日お話すること
    ・開発要件
    ・実装方法選定
    ・SpringSecurityの機能を使った事例
    ・SpringSecurityでは実現できない部分
    Spring AOP(AspectJ)で回避

    View full-size slide

  4. © RAKUS Co., Ltd. 4
    はじめに
    本事例の対象サービス「楽楽電子保存」
    オンライン上で請求書の受取・管理
    はじめに

    View full-size slide

  5. © RAKUS Co., Ltd. 5
    開発要件

    View full-size slide

  6. © RAKUS Co., Ltd. 6
    こんな開発要件がありました。
    無料版ユーザー
    有料版ユーザー
    ● 有料版/無料版で利用できる機能を制限する
    開発要件
    エンドポイント
    制限

    View full-size slide

  7. © RAKUS Co., Ltd. 7
    ● ユーザーの持っている権限に応じてアクセスできる
    データを制限する
    開発要件
    データ制限

    View full-size slide

  8. © RAKUS Co., Ltd. 8
    ● アクセス違反の理由に応じて、エラーメッセージを
    出し分ける
    開発要件
    オプションが有
    効でない
    権限がない
    指定タグに閲覧
    権限がない
    指定帳票に閲覧
    権限がない
    無料版ユーザー
    有料版ユーザー
    有料版ユーザー
    有料版ユーザー

    View full-size slide

  9. © RAKUS Co., Ltd. 9
    開発要件を実現するにあたり実装時
    に遭遇したいくつかの課題を紹介さ
    せていただきます。

    View full-size slide

  10. © RAKUS Co., Ltd. 10
    実装方法選定

    View full-size slide

  11. © RAKUS Co., Ltd. 11
    実装方法の選択肢
    Spring bootを利用しているのでこの前提で
    以下のいずれかの方法で検討しました
    ・Spring security
    ・Spring AOP(AspectJ)
    ・Filter
    実装方法選定

    View full-size slide

  12. © RAKUS Co., Ltd. 12
    実装方法選定
    Spring security 使う強み
    ・セキュリティ機能は最低限の設定で実装できること
    ・一般的な脆弱性の対策を広くカバーしている
    ・単体テストもサポートされている

    View full-size slide

  13. © RAKUS Co., Ltd. 13
    実装方法選定
    Spring AOP(AspectJ) 使う強み
    ・クリーナーコード
    メインロジックから横断的関心(Crosscutting Concern)
    (ロギング、セキュリティなど)を取り除く
    ・メンテナンスが楽になる
    AOPで注入する処理は共通処理として一元管理される

    View full-size slide

  14. © RAKUS Co., Ltd. 14
    実装方法選定
    Filter 使う強み
    ・Springは、Filterを作成するためのサポートクラスも
    提供されている
    ・各コントローラーの前後に共通処理を実行することが
    担保できる

    View full-size slide

  15. © RAKUS Co., Ltd. 15
    実装方法選定
    Spring securityとAOPを併用しました
    現場で認証処理はSpringSecurityで実装されていたので
    認可処理でも簡単に実装できた
    無料版ユーザー
    有料版ユーザー

    View full-size slide

  16. © RAKUS Co., Ltd. 16
    実装方法選定
    指定タグに閲覧
    権限がない
    指定帳票に閲覧
    権限がない
    有料版ユーザー
    有料版ユーザー
    SpringSecurityで実装できない部分も出てしまったので
    Spring AOP(AspectJ)で回避できた
    (セキュリティーは横断的関心(Crosscutting Concern)の
    中で一つなので似合っている)

    View full-size slide

  17. © RAKUS Co., Ltd. 17
    SpringSecurityの機能を使った事例

    View full-size slide

  18. © RAKUS Co., Ltd. 18
    SpringSecurityの機能を使う部分
    SpringSecurityの認可機能なら、
    アクセス権限を制御することは簡単に出来る
    図:HttpServletRequest を認証する(Spring公開ドキュメント)
    ここで触る

    View full-size slide

  19. © RAKUS Co., Ltd. 19
    SpringSecurityの機能を使う部分:実装事例
    現場での実装事例
    ログインの際にSecurityContextのAuthentication情報
    にGrantedAuthority一覧を追加する
    List authorities = List.of(
    new SimpleGrantedAuthority(“MANAGER”)
    );
    SecurityContextHolder.getContext().setAuthentication(
    new UsernamePasswordAuthenticationToken(principal,
    credentials,
    authorities));

    View full-size slide

  20. © RAKUS Co., Ltd. 20
    SpringSecurityの機能を使う部分:実装事例
    http.authorizeHttpRequests(auth -> {
    authenticationProperties.getAuthorities().forEach(authority ->
    auth.requestMatchers(authority.getHttpMethod(),
    authority.getEndPoint())
    .hasAnyRole(authority.getRole()));
    })
    HttpServletRequestsを利用し、認可定義
    Httpメソッドによる
    マッチング
    RequestMatcherによる
    マッチング

    View full-size slide

  21. © RAKUS Co., Ltd. 21
    SpringSecurityの機能を使う部分:実装事例
    AccessDeniedHandlerの処理関数を用意する
    public AccessDeniedHandler accessDeniedHandler() {
    return (request, response, accessDeniedException) -> {
    request.getRequestDispatcher(【該当パス】)
    .forward(request, response);
    };
    }
    無料版/有料版を判断し、
    該当のエラーコントローラーへ移動

    View full-size slide

  22. © RAKUS Co., Ltd. 22
    SpringSecurityの機能を使う部分:実装事例
    http.exceptionHandling(e ->
    e.accessDeniedHandler(accessDeniedHandler()));
    Spring SecurityのAccessDeniedHandlerを定義する

    View full-size slide

  23. © RAKUS Co., Ltd. 23
    SpringSecurityでは実現できない部分
    Spring AOP(AspectJ)で回避

    View full-size slide

  24. © RAKUS Co., Ltd. 24
    Spring AOP(AspectJ)
    Spring認可の課題
    アクセス権限がない時にAccessDeniedExceptionのみを
    返すため、エラーケースを区別するのは簡単にできない
    P22~23で使用してい
    るが、無料版/有料版
    の判断がすごく簡単
    だから!

    View full-size slide

  25. © RAKUS Co., Ltd. 25
    指定タグに閲覧権限がない
    指定帳票に閲覧権限がない
    指定アップロードファイルに閲覧権限がない
    Spring AOP(AspectJ):Spring認可の課題
    ・データベースへ
    アクセスが必要
    ・分岐ケースも
    多い

    View full-size slide

  26. © RAKUS Co., Ltd. 26
    Spring AOP(AspectJ):Spring認可の課題
    複雑で同様処理だが二重実行が発生
    ・認可
    ・エラー出し分け
    AOP

    View full-size slide

  27. © RAKUS Co., Ltd. 27
    AOP概要
    Spring AOP(AspectJ):AOP概要
    クラスを横断した処理(例外処理やロギングなど)をビジ
    ネスロジックから分離するようにコードを記述する
    Advice
    Join points
    Point cut
    Program
    Execution
    Advice:抽出した共通処理
    Joinpoint:Adviceを入れる場所
    (@Before、 @Afterなど)
    Pointcut:Adviceを適用する条件
    例:
    @Before("@annotation(XXX)")
    https://spring.pleiades.io/spring-
    framework/reference/core/aop.html

    View full-size slide

  28. © RAKUS Co., Ltd. 28
    Spring AOP(AspectJ):実装事例
    現場での実装事例
    ・専用アノテーションを作成する
    ・AOPのAdviceを定義して権限チェック処理を実装する
    ・権限チェックのAOPをメソッドに注入する

    View full-size slide

  29. © RAKUS Co., Ltd. 29
    Spring AOP(AspectJ):実装事例
    専用アノテーション
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface BrowsableChecker {
    }
    メソッドのみに使用できる

    View full-size slide

  30. © RAKUS Co., Ltd. 30
    Spring AOP(AspectJ):実装事例
    Advice定義
    AOPのAdviceを定義し、権限チェック処理を実装する
    @Aspect
    @Component
    public class BrowsableCheckerAspect {
    @Before("@annotation(BrowsableChecker)")
    public void check(JoinPoint joinPoint) {
    // 権限判断処理を行う
    }
    }
    メソッドが実行される前に、
    Advice実行
    AOP宣言
    指定したアノテーションが付いて
    いるメソッドのみがAOPの対象

    View full-size slide

  31. © RAKUS Co., Ltd.
    Advice定義(権限判断処理)
    @Before("@annotation(BrowsableChecker)")
    public void check(JoinPoint joinPoint) {
    // パラメーターを取得する
    Object command = joinPoint.getArgs()[0];
    // commandを該当な型に変換する
    if (target instanceof XXXCommand cmd) {
    // データベースからデータを取得して権限チェ
    ック
    // アクセス拒否の場合、例外をThrowする
    }
    }
    Joinpointから
    メソッドの
    パラメーターが取
    得可能
    Spring AOP(AspectJ):実装事例

    View full-size slide

  32. © RAKUS Co., Ltd.
    Spring AOP(AspectJ):実装事例
    AOP注入
    データアクセス制御が必要なサービスのメソッドに
    専用アノテーションを簡単に付ける
    @Service
    public class XXXUpdateService {
    @BrowsableChecker
    public void execute(XXXCommand cmd) {
    // メイン処理を行う(略)
    }
    }
    excuteメソッドの処
    理を実行する前に、
    権限チェックのAOP
    を実行する

    View full-size slide

  33. © RAKUS Co., Ltd.
    Spring AOP(AspectJ):実装事例
    単体テスト
    単体テストでもMockとして共通化に用意する
    public class BrowsableCheckerMock {
    public void setup(XXXCommand command) {
    // 共通Mock処理を行う
    }
    }
    権限チェックMockクラス

    View full-size slide

  34. © RAKUS Co., Ltd.
    Spring AOP(AspectJ):実装事例
    単体テスト
    @SpringBootTest
    @Import([BrowsableCheckerMock.class])
    class XXXUpdateServiceSpec extends Specification {
    def "アクセスする権限がありません"() {
    setup:
    browsableCheckerMock.setup(cmd)
    }
    }
    @Importを定義し、使用する

    View full-size slide

  35. © RAKUS Co., Ltd.
    おわりに
    おわりに
    Spring securityの認可機能はエンドポイント単位も
    データ単位も制限可能
    但し、SpringSecurityの認可で実装すれば、アクセス拒否の時に
    AccessDeniedExceptionのみを返すため、エラーの理由を区別する
    ことができないので注意必要
    セキュリティーとは横断的関心(Crosscutting Concern)の中で一つ
    なのでSpringSecurity認可の代わりに、AOPで回避可能

    View full-size slide

  36. © RAKUS Co., Ltd.
    おわりに
    Spring Security in Action Laurentiu Spilca
    参照
    Spring によるアスペクト指向プログラミング
    https://spring.pleiades.io/spring-
    framework/reference/core/aop.html
    Spring Security - リファレンス
    https://spring.pleiades.io/spring-security/reference/

    View full-size slide

  37. © RAKUS Co., Ltd.
    ご清聴ありがとうございました

    View full-size slide