2017-03-01 15 views
2

私のアプリケーションにセキュリティを実装する際に問題があります... 私はカスタム認証を持っていて、@PreAuthorizeを使用してユーザー認証を処理しています。これは正常に動作します。今、私は2人のユーザー、「管理者」と「ジョン、方法春のセキュリティのベストアクセス 'アクセス'ユーザー

@RequestMapping(value = "/load/{id}", method = RequestMethod.GET) 
@ResponseBody 
public StudentYearViewModel load(@PathVariable long id) { 
    return ModelMapper.map(iStudentService.loadByEntityId(id), StudentViewModel.class); 
} 

呼び出すことができます「管理者」は、すべての学生のインスタンスに対してこのメ​​ソッドを使用することができたときに自分のアプリケーションに意味し、ユーザごとにアクセス制御を実装したいが、 「ジョン」は彼のクラスメートだけを見ることができます! すべてのユーザーがこのメソッドを呼び出すことができます(@ PreAuthorizeは適切ではありませんが、アクセスは制限されています)。 今や一般的なやり方はありますか?

はACLの最良の方法です?(最良の例を持っている?)

HDIVフレームワーク私は私の問題を解決するのに役立つ可能性が?

最適な解決策は何ですか?

答えて

1

AdminとJohn ROLE_ADMIN、ROLE_USERにそれぞれ異なる役割を割り当てます。次に、コントローラ内のロールをチェックし、対応するサービスメソッドをコールして、ロールに従ってデータを返します。

@RequestMapping(value = "/load/{id}", method = RequestMethod.GET) 
@ResponseBody 
public StudentYearViewModel load(HttpServletRequest request, Authentication authentication, @PathVariable long id) { 

    if (request.isUserInRole("ROLE_ADMIN")) { 
     return ModelMapper.map(iStudentService.loadByEntityId(id), StudentViewModel.class); //return all records 
    } if (request.isUserInRole("ROLE_USER")) { 
    String username = authentication.getName(); //get logged in user i.e. john 
     return ModelMapper.map(iStudentService.loadByEntityId(id, username), StudentViewModel.class); //return records by username 
    } 
} 
+0

ご注意いただきありがとうございます!私はたくさんのROLEを作成する必要があります。それは最高の解決策ですか? –

1

あなたは@PostFilter@PreFilterを見てみたいです。彼らはほとんど@PreAuthorizeのように動作しますが、リストから結果を削除できます。また、あなたはまだそれをやっていないと仮定して、あなたのユーザーに異なる役割を割り当てる必要があります。

管理者のようにすべてを見ることができるようなグローバルルールは、PermissionEvaluatorの具体的な実装を記述することで実装できます。あなたはそれを次に追加します。MethodSecurityExpressionHandler

時間は簡単な例です。

このコードはテキストエディタで書かれています。これは、コンパイルして非常に単純

Aを必要なステップを表示するにはここでしかありませんかもしれPermissionEvaluator

public class MyPermissionEvaluator implements PermissionEvaluator { 
    private static final SimpleGrantedAuthority AUTHORITY_ADMIN = new SimpleGrantedAuthority('admin'); 

    public boolean hasPermission(final Authentication authentication, final Object classId, final Object permission) { 
     boolean permissionGranted = false; 

     // admin can do anything 
     if (authentication.getAuthorities().contains(AUTHORITY_ADMIN)) { 
      permissionGranted = true; 
     } else { 
      // Check if the logged in user is in the same class 
     } 
     return permissionGranted; 
    } 

    @Override 
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, 
      Object permission) { 
     return false; 
    } 

} 

その後方法のセキュリティは

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { 

    @Bean 
    public MethodSecurityExpressionHandler methodSecurityExpressionHandler(final PermissionEvaluator permissionEvaluator){ 
     DefaultMethodSecurityExpressionHandler securityExpressionHandler = new DefaultMethodSecurityExpressionHandler(); 
     securityExpressionHandler.setPermissionEvaluator(permissionEvaluator); 
     return securityExpressionHandler; 
    } 

    @Bean 
    public PermissionEvaluator permissionEvaluator() { 
     return new MyPermissionEvaluator(); 
    } 
} 

は、今、私たちは法

に私たちのフィルタを使用することができます設定
@PostFilter("hasPermission(filterObject.getClassId(), 'READ')") 
@Override 
public List<Student> getAll() { 
    return querySomeStudents(); 
} 

hasPermission i n @PostFilter ACLはMyPermissionEvaluatorhasPermissionを呼び出します。 filterObjectは、リスト内の個々の項目を参照します。コードがfalseを返す場合は、リストから項目を削除します。

+0

ありがとうございます!あなたのソリューションははるかに良いですが、私は質問があります。 "filterObject.getClassId()"はどのように動作するのですか?このパフォーマンスは良いですか?いくつかのものを削除するよりも、すべてのリストを取得するための最良の方法はありますか?私はDBでこのフィルタを書いてもOKではないと思いますか? –

+0

'filterObject'は、イントロスペクションを使用してSpringによって取得されます。パフォーマンスは非常に相対的な用語です。パフォーマンスの問題がなくても多くの場所で使用しています。私の気持ちは、最もクリーンで、コードを管理し、パフォーマンスの問題が発生したときに対処するのが最も簡単なものを書くことです。データベース内のデータをフィルタリングすることは、パフォーマンスの観点から見れば「良い」ことです。データベースのフィルタリングは、ネットワークI/Oを削減することもできます。 – Leon

関連する問題