0


security权限管理详解

一、授权流程

用户登录成功后会将用户信息保存在Authencation对象中,Authencation接口中有一个getAuthorities()方法返回的是用户的权限

Collection<? extends GrantedAuthority> getAuthorities();

现有系统可以基于角色做权限管理也可以使用资源(权限字符串)做权限管理,这里的GrantedAuthority是角色还是资源呢?

  • 如果 业务是基于角色做的权限管理,即用户->角色->资源,那么返回的是用户的角色
  • 如果业务是基于资源(权限)做的权限管理,即用户->权限->资源,返回的是用户的权限
  • 如果基于角色+权限做的权限管理,即用户->角色->权限->资源,返回的是用户的权限

security在角色和权限的处理方式上基本一样的,唯一区别就是很多时候会自动给角色增加一个ROLE_前缀,而权限不会添加

二、权限管理策略

1、基于URL做权限管理(过滤器技术实现)

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //创建内存数据源
    public UserDetailsService userDetailsService(){
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        //admin用户 具有ADMIN 和 USER角色
        inMemoryUserDetailsManager.createUser(User.withUsername("admin").password("{noop}123").roles("ADMIN","USER").build());
        //user用户 具有USER角色
        inMemoryUserDetailsManager.createUser(User.withUsername("user").password("{noop}123").roles("USER").build());
        //info用户具有READ_INFO权限操作
        inMemoryUserDetailsManager.createUser(User.withUsername("info").password("{noop}123").authorities("READ_INFO").build());
        return inMemoryUserDetailsManager;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //访问/admin必须有ADMIN角色
                .mvcMatchers("/admin").hasRole("ADMIN")
                //访问/user需要USER角色或者ADMIN角色
                .mvcMatchers("/user").hasAnyRole("ADMIN","USER")
                //访问/info必须有READ_INFO权限
                .mvcMatchers("/info").hasAuthority("READ_INFO")
                .anyRequest().authenticated()
                .and().formLogin()
                .and().csrf().disable();
    }
}

备注1:上面的hasRole()、hasAuthority()称为权限表达式,类如下

53c28f640566f3e559380796f08b71bf.png

dc07a98f1879defc97a203572730e7ef.png

备注2:mvcMatchers、antMatchers、regexMatchers区别是?

1、mvcMatchers是在antMatchers之后增加的,两个都可以传递请求方式以及多个路径,如下

.mvcMatchers(HttpMethod.GET,"/admin","/test").hasRole("ADMIN")
.antMatchers(HttpMethod.GET,"/admin","/test").hasRole("ADMIN")

2、mvcMatchers相对antMatchers更加强大一些,比如mvcMatchers("/admin")可以匹配“/admin"还可以匹配"/admin/" 、"/admin/a"、"/admin.html",但是.antMatchers("/admin")只能匹配"/admin"

3、regexMatchers则是可以通过正在表达式匹配

2、基于方法策略权限管理(基于AOP技术实现)

基于方法的权限管理是基于aop技术实现的,security中通过MethodSecurityInterceptor提供相关实现,不同在于FilterSecurityInterceptor只是请求前置进行处理,而MethodSecurityInterceptor除了前置请求还可以进行后置请求,前置是在请求之前判断是否具有相应的权限,后置则是对方法的执行结果进行二次过滤,前置和后置分别对应了不同的实现类,

/**
 * EnableGlobalMethodSecurity是开启全局方法的权限注解
 * prePostEnabled开启security提供的四个权限注解,这四个注解支持上面的权限表达式
 *      @PostFilter在目标方法执行之后对方法的返回结果进行过滤
 *      @PostAuthorize在目标方法执行之后进行权限校验
 *      @PreAuthorize在目标方法执行之前进行校验
 *      @PreFilter在目标方法执行之前对参数进行过滤
 * securedEnabled开启security提供的@secured,只支持角色,不支持权限表达式
 *      @secured访问目标方法必须具备相应的角色
 * jsr250Enabled开启JSR-250提供的三个权限注解,同样只支持角色不支持权限表达式
 *      @DenyAll拒绝所有访问
 *      @PermitAll允许所有访问
 *      @RolesAllowed访问目标方法必须具备相应的角色
 *
 *这些基于方法的权限注解,一般来说只要设置prePostEnabled=true就够了
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true,jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //创建内存数据源
    @Bean
    public UserDetailsService userDetailsService(){
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        //admin用户 具有ADMIN 和 USER角色
        inMemoryUserDetailsManager.createUser(User.withUsername("admin").password("{noop}123").roles("ADMIN","USER").build());
        //user用户 具有USER角色
        inMemoryUserDetailsManager.createUser(User.withUsername("user").password("{noop}123").roles("USER").build());
        //info用户具有READ_INFO权限操作
        inMemoryUserDetailsManager.createUser(User.withUsername("info").password("{noop}123").authorities("READ_INFO").build());
        return inMemoryUserDetailsManager;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and().formLogin()
                .and().csrf().disable();
    }
}

使用

@RestController
@RequestMapping("/demo")
public class DemoController {
    /**
    *可以使用权限表达式以及and or
    *除了角色还可以使用权限hasAuthority
    */
    @PreAuthorize("hasRole('ADMIN') and authentication.name=='admin'")
    @GetMapping("/user")
    public String user(){
        return "user";
    }
    /**
    * 传的参数如果和登录用户的账号相同才能访问
    */
    @PreAuthorize("authentication.name==#username")
    @GetMapping("/name")
    public String name(String username){
        return "name";
    }
    /**
    * 请求方法前对参数过滤 参数必须是数组、集合
    */
    @PreFilter(value = "filterTarget.id%2!=0",filterTarget = "users")
    @GetMapping("/users")
    public String name(@RequestBody List<User> users){
        return "user";
    }
    /**
    * 返回指定的对象
    */
    @PostAuthorize("returnObject.id==1")
    @GetMapping("/userId")
    public String userId(@RequestBody List<User> users){
        return "userId";
    }
    /**
    * 过滤方法的返回值 返回值是数组或者集合
    */
    @PostFilter("filterTarget.id%2==0")
    @GetMapping("/all")
    public String all(@RequestBody List<User> users){
        return "all";
    }
    
    /**
    * 只能判断角色,可以是多个 ,具有其中一个即可
    */
    @Secured("{ROLE_USER,ROLE_ADMIN}")
    @GetMapping("/Secured")
    public String secured(@RequestBody List<User> users){
        return "Secured";
    }
    
    /**
    * 放行所有
    */
    @PermitAll
    @GetMapping("/PermitAll")
    public String permitAll(@RequestBody List<User> users){
        return "PermitAll";
    }
    
    /**
    * 拒绝所有请求
    */
    @DenyAll
    @GetMapping("/denyall")
    public String denyAll(){
        return "denyall";
    }
    
    /**
    * 具有其中一个角色即可
    */
    @RolesAllowed("{ROLE_ADMIN,ROLE_USER}")
    @GetMapping("/rolseAll")
    public String rolseAll(){
        return "rolseAll";
    }
}
标签: 安全

本文转载自: https://blog.csdn.net/qq_34491508/article/details/125961114
版权归原作者 程序三两行 所有, 如有侵权,请联系我们删除。

“security权限管理详解”的评论:

还没有评论