舞台裏

Qiita が表でこっちが裏。こっそりやっていく。

2.1. Securing Service Methods

Spring Security ACL Plugin - Reference Documentation

There are two primary use cases for ACL security: determining whether a user is allowed to perform an action on an instance before the action is invoked, and restricting access to single or multiple instances after methods are invoked (this is typically implemented by collection filtering).

ACL セキュリティについて2つの主要なユースケースがあります。
アクションが実行される前に、あるインスタンスでのアクションを実行することをユーザに許可するかどうかを決定する、そしてメソッドが実行された後で1つかもしくは複数のインスタンスへのアクセスを制限する(よくコレクションのフィルターで実装される)

You can call aclUtilService.hasPermission() explicitly, but this tends to clutter your code with security logic that often has little to do with business logic.

aclUtilService.hasPermission() を明示的に呼ぶことができます。しかし、ビジネスロジックと関係のないセキュリティロジックを一緒にするとコードは複雑になる傾向があります。

Instead, Spring Security provides some convenient annotations that are used to wrap your method calls in access checks.

代わりに、 Spring Security はいくつかの便利なアノテーションを提供しています。
それらのアノテーションはアクセスチェックの中でメソッドの呼び出しをラップするのに使われます。

There are four annotations:

4つのアノテーションがあります。

  • @PreAuthorize
  • @PreFilter
  • @PostAuthorize
  • @PostFilter

The annotations use security-specific Spring expression language (SpEL) expressions - see the documentation for the available standard and method expressions.

アノテーションはセキュリティ固有の Spring 式言語(SpEL) の式を使用します。
有効な標準やメソッド式についてドキュメントを見てください。

Here’s an example service that manages a Report domain class and uses these annotations and expressions:

ここに、 Report ドメインクラスを管理し、アノテーションと式を使用するサービスの例を示します。

import org.springframework.security.access.prepost.PostFilter
import org.springframework.security.access.prepost.PreAuthorize
import grails.transaction.Transactional

import com.yourapp.Report

class ReportService {

   @PreAuthorize("hasPermission(#id, 'com.yourapp.Report', read) or " +
                 "hasPermission(#id, 'com.yourapp.Report', admin)")
   Report getReport(long id) {
      Report.get(id)
   }

   @Transactional
   @PreAuthorize("hasRole('ROLE_USER')")
   Report createReport(params) {
      Report report = new Report(params)
      report.save()
      report
   }

   @PreAuthorize("hasRole('ROLE_USER')")
   @PostFilter("hasPermission(filterObject, read) or " +
               "hasPermission(filterObject, admin)")
   List getAllReports(params = [:]) {
      Report.list(params)
   }

   @Secured(['ROLE_USER', 'ROLE_ADMIN'])
   String getReportName(long id) {
      Report.get(id).name
   }

   @Transactional
   @PreAuthorize("hasPermission(#report, write) or " +
                 "hasPermission(#report, admin)")
   Report updateReport(Report report, params) {
      report.properties = params
      report.save()
      report
   }

   @Transactional
   @PreAuthorize("hasPermission(#report, delete) or " +
                 "hasPermission(#report, admin)")
   void deleteReport(Report report) {
      report.delete()
   }
}

The configuration specifies these rules:

設定はこれらのルールを指定しています。

  • getReport requires that the authenticated user have BasePermission.READ or BasePermission.ADMIN for the instance
  • createReport requires ROLE_USER
  • getAllReports requires ROLE_USER and will have elements removed from the returned List that the user doesn’t have an ACL grant for; the user must have BasePermission.READ or BasePermission.ADMIN for each element in the list; elements that don’t have access granted will be removed
  • getReportName requires that the authenticated user have either ROLE_USER or ROLE_ADMIN (but no ACL rules)
  • updateReport has no role restrictions but must satisfy the requirements of the aclReportWriteVoter voter (which has the ACL_REPORT_WRITE config attribute), i.e. BasePermission.ADMINISTRATION or BasePermission.WRITE
  • deleteReport has no role restrictions but must satisfy the requirements of the aclReportDeleteVoter voter (which has the ACL_REPORT_DELETE config attribute), i.e. BasePermission.ADMINISTRATION or BasePermission.DELETE

  • getReport は認証されたユーザがインスタンスに対する BasePermission.READBasePermission.ADMIN を持つことを要求します。

  • createReportROLE_USER を要求します
  • getAllReportsROLE_USER を要求し、 return されたリストのうち、ユーザに ACL が与えられていない要素が削除されます。
    ユーザは BasePermission.READBasePermission.ADMIN をリストの各要素に対して持たなければなりません。
    アクセスが許可されていない要素は削除されます。
  • getReportName は認証されたユーザが ROLE_USERROLE_ADMIN を持つことを要求します(ACL ルールではありません)
  • updateReport はロールによる制限を持ちません。しかし、 aclReportWriteVoter Voter による要求を満たす必要があります。
    (voter は ACL_REPORT_WRITE 設定属性を持ちます)
    つまり BasePermission.ADMINISTRATION または BasePermission.WRITE です。
  • deleteReport はロールによる制約がありません。しかし、 aclReportDeleteVoter Voter による要求を満たす必要があります。
    (voter は ACL_REPORT_DELETE 設定属性を持ちます)
    つまり、 BasePermission.ADMINISTRATION または BasePermission.DELETE です。