spring security中@PreAuthorize、@PostAuthorize、@PreFilter和@PostFilter四者的區別


spring security中可以通過表達式控制方法權限:

  Spring Security中定義了四個支持使用表達式的注解,分別是@PreAuthorize、@PostAuthorize、@PreFilter和@PostFilter。其中前兩者可以用來在方法調用前或者調用后進行權限檢查,后兩者可以用來對集合類型的參數或者返回值進行過濾。要使它們的定義能夠對我們的方法的調用產生影響我們需要設置global-method-security元素的pre-post-annotations=”enabled”,默認為disabled。

   <security:global-method-security pre-post-annotations="disabled"/>

 使用@PreAuthorize和@PostAuthorize進行訪問控制

       @PreAuthorize可以用來控制一個方法是否能夠被調用。

@Service

public class UserServiceImpl implements UserService {

   @PreAuthorize("hasRole('ROLE_ADMIN')")

   public void addUser(User user) {

      System.out.println("addUser................" + user);

   }

   @PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")

   public User find(int id) {

      System.out.println("find user by id............." + id);

      return null;

   }

}

  在上面的代碼中我們定義了只有擁有角色ROLE_ADMIN的用戶才能訪問adduser()方法,而訪問find()方法需要有ROLE_USER角色或ROLE_ADMIN角色。使用表達式時我們還可以在表達式中使用方法參數。

public class UserServiceImpl implements UserService {

   /**

    * 限制只能查詢Id小於10的用戶

   */

   @PreAuthorize("#id<10")

   public User find(int id) {

      System.out.println("find user by id........." + id);

      return null;

   }

   /**

    * 限制只能查詢自己的信息

    */

   @PreAuthorize("principal.username.equals(#username)")

   public User find(String username) {

      System.out.println("find user by username......" + username);

      return null;

   }

   /**

    * 限制只能新增用戶名稱為abc的用戶

    */

   @PreAuthorize("#user.name.equals('abc')")

   public void add(User user) {

      System.out.println("addUser............" + user);

   }

}

   在上面代碼中我們定義了調用find(int id)方法時,只允許參數id小於10的調用;調用find(String username)時只允許username為當前用戶的用戶名;定義了調用add()方法時只有當參數user的name為abc時才可以調用。

   有時候可能你會想在方法調用完之后進行權限檢查,這種情況比較少,但是如果你有的話,Spring Security也為我們提供了支持,通過@PostAuthorize可以達到這一效果。使用@PostAuthorize時我們可以使用內置的表達式returnObject表示方法的返回值。

下面這一段示例代碼:

@PostAuthorize("returnObject.id%2==0")

   public User find(int id) {

      User user = new User();

      user.setId(id);

      return user;

   }

       上面這一段代碼表示將在方法find()調用完成后進行權限檢查,如果返回值的id是偶數則表示校驗通過,否則表示校驗失敗,將拋出AccessDeniedException。需要注意的是@PostAuthorize是在方法調用完成后進行權限檢查,它不能控制方法是否能被調用,只能在方法調用完成后檢查權限決定是否要拋出AccessDeniedException。

使用@PreFilter和@PostFilter進行過濾

       使用@PreFilter和@PostFilter可以對集合類型的參數或返回值進行過濾。使用@PreFilter和@PostFilter時,Spring Security將移除使對應表達式的結果為false的元素。

   @PostFilter("filterObject.id%2==0")

  public List<User> findAll() {

      List<User> userList = new ArrayList<User>();

      User user;

      for (int i=0; i<10; i++) {

         user = new User();

         user.setId(i);

         userList.add(user);

      }

      return userList;

   }

       上述代碼表示將對返回結果中id不為偶數的user進行移除。filterObject是使用@PreFilter和@PostFilter時的一個內置表達式,表示集合中的當前對象。當@PreFilter標注的方法擁有多個集合類型的參數時,需要通過@PreFilter的filterTarget屬性指定當前@PreFilter是針對哪個參數進行過濾的。

如下面代碼就通過filterTarget指定了當前@PreFilter是用來過濾參數ids的。

  1.  
    @PreFilter(filterTarget="ids", value="filterObject%2==0")
  2.  
     
  3.  
    public void delete(List<Integer> ids, List<String> usernames) {
  4.  
     
  5.  
    ...
  6.  
     
  7.  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM