美文网首页
@EnableGlobalMethodSecurity三方法详解

@EnableGlobalMethodSecurity三方法详解

作者: zenghi | 来源:发表于2019-03-10 22:50 被阅读0次

    @EnableGlobalMethodSecurity三方法详解

    要开启Spring方法级安全,在添加了@Configuration注解的类上再添加@EnableGlobalMethodSecurity注解即可

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled=true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    }
    

    其中注解@EnableGlobalMethodSecurity有几个方法:

    • prePostEnabled 确定 前置注解[@PreAuthorize,@PostAuthorize,..] 是否启用
    • securedEnabled 确定安全注解 [@Secured] 是否启用
    • jsr250Enabled 确定 JSR-250注解 [@RolesAllowed..]是否启用

    在同一个应用程序中,可以启用多个类型的注解,但是只应该设置一个注解对于行为类的接口或者类。如:

    • 一个程序启用多个类型注解:

      @Configuration
      @EnableWebSecurity
      @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true))
      public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
          ...
      }
      
    • 但是只应该设置一个注解对于行为类的接口或者类

      public interface UserService {
        List<User> findAllUsers();
      
        @PreAuthorize("hasAnyRole('user')")
        void updateUser(User user);
      
          // 下面不能设置两个注解,如果设置两个,只有其中一个生效
          // @PreAuthorize("hasAnyRole('user')")
        @Secured({ "ROLE_user", "ROLE_admin" })
        void deleteUser();
      }
      

    启用securedEnabled

    先启用securedEnabled

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(securedEnabled = true))
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        ...
    }
    

    在调用的接口或方法使用如下:

    public interface UserService {
        List<User> findAllUsers();
        
        @Secured({"ROLE_user"})
        void updateUser(User user);
    
        @Secured({"ROLE_admin", "ROLE_user1"})
        void deleteUser();
    }
    

    @Secured注解是用来定义业务方法的安全配置。在需要安全[角色/权限等]的方法上指定 @Secured,并且只有那些角色/权限的用户才可以调用该方法。

    @Secured缺点(限制)就是不支持Spring EL表达式。不够灵活。并且指定的角色必须以ROLE_开头,不可省略。

    在上面的例子中,updateUser 方法只能被拥有user权限的用户调用。deleteUser 方法只能够被拥有admin 或者user1 权限的用户调用。而如果想要指定"AND"条件,即调用deleteUser方法需同时拥有ADMINDBA角色的用户,@Secured便不能实现。

    这时就需要使用prePostEnabled提供的注解@PreAuthorize/@PostAuthorize

    启用prePostEnabled

    先启用prePostEnabled

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        ...
    }
    

    在调用的接口或方法使用:

    public interface UserService {
        List<User> findAllUsers();
    
        @PostAuthorize ("returnObject.type == authentication.name")
        User findById(int id);
    
        @PreAuthorize("hasRole('ADMIN')")
        void updateUser(User user);
        
        @PreAuthorize("hasRole('ADMIN') AND hasRole('DBA')")
        void deleteUser(int id);
    }
    

    该注解更适合方法级的安全,也支持Spring 表达式语言,提供了基于表达式的访问控制。参见常见内置表达式了解支持表达式的完整列表

    上面只使用到了一个注解@PreAuthorize,启用prePostEnabled后,提供有四个注解:

    • @PreAuthorize 进入方法之前验证授权。可以将登录用户的roles参数传到方法中验证。

      一些用法:

      // 只能user角色可以访问
      @PreAuthorize ("hasAnyRole('user')")
      // user 角色或者 admin 角色都可访问
      @PreAuthorize ("hasAnyRole('user') or hasAnyRole('admin')")
      // 同时拥有 user 和 admin 角色才能访问
      @PreAuthorize ("hasAnyRole('user') and hasAnyRole('admin')")
      // 限制只能查询 id 小于 10 的用户
      @PreAuthorize("#id < 10")
      User findById(int id);
      
      // 只能查询自己的信息
       @PreAuthorize("principal.username.equals(#username)")
      User find(String username);
      
      // 限制只能新增用户名称为abc的用户
      @PreAuthorize("#user.name.equals('abc')")
      void add(User user)
      
    • @PostAuthorize 该注解使用不多,在方法执行后再进行权限验证。 适合验证带有返回值的权限。Spring EL 提供 返回对象能够在表达式语言中获取返回的对象returnObject。如:

      // 查询到用户信息后,再验证用户名是否和登录用户名一致
      @PostAuthorize("returnObject.name == authentication.name")
      @GetMapping("/get-user")
      public User getUser(String name){
          return userService.getUser(name);
      }
      // 验证返回的数是否是偶数
      @PostAuthorize("returnObject % 2 == 0")
      public Integer test(){
          // ...
          return id;
      }
      
    • @PreFilter 对集合类型的参数执行过滤,移除结果为false的元素

      // 指定过滤的参数,过滤偶数
      @PreFilter(filterTarget="ids", value="filterObject%2==0")
      public void delete(List<Integer> ids, List<String> username)
      
    • @PostFilter 对集合类型的返回值进行过滤,移除结果为false的元素

      @PostFilter("filterObject.id%2==0")
      public List<User> findAll(){
          ...
          return userList;
      }
      

    对于前面使用@Secured注解的缺点,现在使用@PreAuthorize/@PostAuthorize

    public interface UserService {
        List<User> findAllUsers();
    
        @PostAuthorize ("returnObject.type == authentication.name")
        User findById(int id);
    
        @PreAuthorize("hasRole('ADMIN')")
        void updateUser(User user);
        
        @PreAuthorize("hasRole('ADMIN') AND hasRole('DBA')")
        void deleteUser(int id);
    }
    

    启用jsr250Enabled

    jsr250Enabled注解比较简单,只有

    • @DenyAll 拒绝所有访问
    • @RolesAllowed({"USER", "ADMIN"}) 该方法只要具有"USER", "ADMIN"任意一种权限就可以访问。这里可以省略前缀ROLE_,实际的权限可能是ROLE_ADMIN
    • @PermitAll 允许所有访问

    相关文章

      网友评论

          本文标题:@EnableGlobalMethodSecurity三方法详解

          本文链接:https://www.haomeiwen.com/subject/pjlmpqtx.html