2017-03-01 1 views
2

J'ai un problème pour implémenter la sécurité dans mon application ... J'ai une authentification personnalisée et utilise @PreAuthorize pour gérer mon autorisation utilisateur. Cela fonctionne bien. Maintenant, je veux mettre en œuvre le contrôle d'accès pour chaque utilisateur, ce qui signifie dans ma demande lorsque deux utilisateurs, « admin » et « John », pourrait appeler la méthodeMeilleure implémentation 'Accès' Utilisateur dans la sécurité de printemps

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

« Admin » peuvent utiliser cette méthode pour toutes les instances de l'élève, mais 'John' peut voir seulement son camarade de classe! Tous les utilisateurs peuvent appeler cette méthode (@PreAuthorize ne convient pas), mais leur accès est limité COMMENT cela? Maintenant, d'une manière générale?

est ACL meilleure façon? (A meilleur exemple?)

cadre HDIV pourrait me aider à résoudre mon problème ??

quelle est la meilleure solution ???

Répondre

1

Affectez deux rôles différents à Admin et à John ROLE_ADMIN, ROLE_USER respectivement. Ensuite, vérifiez le rôle dans le contrôleur et appelez la méthode de service correspondante pour renvoyer les données en fonction de leur rôle.

@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

merci pour votre attention! Je devrais créer beaucoup de RÔLE .... pour tous les étudiants !! Est-ce la meilleure solution !! ???? –

1

Vous voulez regarder @PostFilter et @PreFilter. Ils fonctionnent à peu près comme @PreAuthorize, mais peuvent supprimer les résultats des listes. Vous souhaitez également attribuer des rôles différents à vos utilisateurs, en supposant que vous ne le faites pas déjà.

Règles globales, comme administrateur pouvant tout voir, vous pouvez implémenter en écrivant une implémentation concrète de PermissionEvaluator. Vous ajoutez ensuite cela au MethodSecurityExpressionHandler

Temps pour un exemple simple.

Ce code a été écrit dans un éditeur de texte. Il ne peut pas compiler et est seulement ici pour montrer les étapes nécessaires

Une très simpliste 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; 
    } 

} 

Ensuite, configurer la sécurité de la méthode

@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(); 
    } 
} 

Maintenant, nous pouvons utiliser notre filtre sur une méthode

@PostFilter("hasPermission(filterObject.getClassId(), 'READ')") 
@Override 
public List<Student> getAll() { 
    return querySomeStudents(); 
} 

hasPermission i n le @PostFilter ACL appellera hasPermission dans MyPermissionEvaluator. filterObject fait référence aux différents éléments de la liste. Où que vous code renvoie false, il supprimera l'élément de la liste.

+0

merci !! votre solution est tellement mieux mais j'ai une question. "filterObject.getClassId()" comment fonctionne Work ??? Cette performance est-elle bonne? Est-ce le meilleur moyen d'obtenir la liste que d'en supprimer une? Je pense que si j'écris ce filtre dans DB n'est pas OK ?? –

+0

'filterObject' est obtenu par Spring en utilisant l'introspection. La performance est un terme très relatif. Je l'utilise dans beaucoup d'endroits sans problèmes de performance. Mon sentiment est d'écrire le code le plus propre, le plus facile à maintenir et de résoudre les problèmes de performance lorsqu'ils surviennent.Le filtrage des données dans la base de données est "meilleur" du point de vue des performances, en supposant que vous réussissiez à indexer. Le filtrage sur la base de données peut également réduire les E/S réseau. – Leon