とりあえず以下の解決策を思いつきました。私のプロジェクトはかなり単純なので、これはより複雑なプロジェクトではうまくいかないかもしれません。
- ユーザーは、特定のクラスのエンティティをすべて読み取るか、まったく読み取ることができません。
したがって、任意のクエリ メソッドに を@PreAuthorize
含むアノテーションを付けることができますhasRole
。
これに対する例外は、Container
私のプロジェクトのエンティティです。のサブクラスを含めることができCompound
、ユーザーはそれらすべてを表示する権限を持っていない場合があります。それらはフィルターでなければなりません。
そのために、User
andRole
エンティティを作成しました。Compound
と OneToOne の関係がRole
あり、そのロールはその の「read_role」ですCompound
。多対多の関係がありますUser
。Role
@Entity
public abstract class Compound {
//...
@OneToOne
private Role readRole;
//...
}
私のリポジトリはすべて実装されQueryDSLPredicateExecutor
ており、ここでは非常に便利です。リポジトリでカスタムの findBy メソッドを作成する代わりに、サービス レイヤーでのみ作成し、 と を使用repositry.findAll(predicate)
しrepository.findOne(predicate)
ます。述語は、実際のユーザー入力と「セキュリティ フィルター」を保持します。
@PreAuthorize("hasRole('read_Container'")
public T getById(Long id) {
Predicate predicate = QCompoundContainer.compoundContainer.id.eq(id);
predicate = addSecurityFilter(predicate);
T container = getRepository().findOne(predicate);
return container;
}
private Predicate addSecurityFilter(Predicate predicate){
String userName = SecurityContextHolder.getContext().getAuthentication().getName();
predicate = QCompoundContainer.compoundContainer.compound.readRole
.users.any().username.eq(userName).and(predicate);
return predicate;
}
注:QCompoundContainer
は、QueryDSL によって生成される「メタモデル」クラスです。
最後に、おそらく からContainer
への QueryDSL パスを初期化する必要がありUser
ます。
@Entity
public abstract class CompoundContainer<T extends Compound>
//...
@QueryInit("readRole.users") // INITIALIZE QUERY PATH
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL,
targetEntity=Compound.class)
private T compound;
//...
}
この最後の手順を省略すると、NullPointerException
.
さらなるヒント:CompoundService
保存時にロールを自動的に設定します:
if (compound.getReadRole() == null) {
Role role = roleRepository.findByRoleName("read_" + getCompoundClassSimpleName());
if (role == null) {
role = new Role("read_" + getCompoundClassSimpleName());
role = roleRepository.save(role);
}
compound.setReadRole(role);
}
compound = getRepository().save(compound)
これは機能します。欠点は少し明白です。同じことが、同じクラス実装Role
のすべてのインスタンスに関連付けられています。Compound