SpringSecurity-入门2-简单的用户授权

文章目录

  • 1. Security 实现授权的基本方式
    • a. 基于配置的对 url 授权
    • b. 基于注解的对方法级别的授权

Spring Security 的权限分控制也是参考 RBAC 模型来的,由 用户角色权限 等基础部分组成,然后再这个基础之上进行设计和开发而来的一套安全框架。

1. Security 实现授权的基本方式

我认为 Spring Security 的认证方式无非是三种如下所示:
我这里只是简单的测试一下前两种的认证方式,第三种很常用,但是比较复杂,下次再写

  • 基于配置的对 url 授权
  • 基于注解的对方法级别的授权
  • 动态的实现授权认证

a. 基于配置的对 url 授权

构建项目的过程自动忽略了,由于不需要从数据库中读取权限,所以本次不需要与数据库交互,采用简单的从内存中读取用户。
初始化环境:
用户三个:
admin 密码 admin 角色 test,admin
test 密码 test 角色 test
dev 密码 dev 角色 dev
资源url:
/admin/add
/admin/upodate
/test/add
/test/upodate
/dev/add
/dev/upodate

配置用户


// 密码器
@Bean
public PasswordEncoder passwordEncoder(){
   return new BCryptPasswordEncoder();
}

// 配置基础的用户三个
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
            .withUser("admin").password(passwordEncoder().encode("admin")).roles("test","admin")
            .and()
            .withUser("test").password(passwordEncoder().encode("test")).roles("test")
            .and()
            .withUser("dev").password(passwordEncoder().encode("dev")).roles("dev")
    ;
}

// 配置url的权限和授权
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            // 有 admin 角色的可以访问所有的 admin/ 开头的请求
            .antMatchers("/admin/**").hasRole("admin")
            // 有 test 角色的可以访问所有的 test/ 开头的请求
            .mvcMatchers("/test/**").hasRole("test")
            // 有 admin 或者 dev 角色的都可以访问所有的 dev/ 开头的请求
            .antMatchers("/dev/**").hasAnyRole("admin","dev","test")
            // 其他请求只要登录就可以访问
            .anyRequest().authenticated()
            .and()
            // 开启表单登录和登陆成功后的url url默认方式是POST方式
            .formLogin()
            .successForwardUrl("/index")
            ;
}

admin controller

@RestController
@RequestMapping("/admin")
public class AdminController {
    @GetMapping("/add")
    public String add(){
        return this.getClass()+"添加的方法";
    }
    @GetMapping("/update")
    public String update(){
        return this.getClass()+"更新的方法的方法";
    }
}

test controller

@RestController
@RequestMapping("/test")
public class TestController {
    @GetMapping("/add")
    public String add(){
        return this.getClass()+"添加的方法";
    }
    @GetMapping("/update")
    public String update(){
        return this.getClass()+"更新的方法的方法";
    }
}

dev controller

@RestController
@RequestMapping("/dev")
public class DevController {
    @GetMapping("/add")
    public String add(){
        return this.getClass()+"添加的方法";
    }
    @GetMapping("/update")
    public String update(){
        return this.getClass()+"更新的方法的方法";
    }
}

登录成功后的index请求

/**
 * @author logic
 */
@RestController
public class IndexController {

    @PostMapping("/index")
    public String index(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authentication.getName()+"登录成功";
    }

}

预测结果:

  1. admin 可以访问所有的url 因为 admin 有admintest 两个角色,所以 admin/**、和 test/** 的所有请求都可以访问,然后 dev/** 配置了只要有 admin 或者 dev test 角色的都可以访问,所以admin用户可以访问多有的url
  2. test 用户可以访问 test/**dev/** 的所有url
  3. dev 用户只能访问 dev/**
  4. 其他未分配的url只要登录即可访问,配置过的url需要对应的权限才能访问

结果截图:

admin 用户的截图
SpringSecurity-入门2-简单的用户授权_第1张图片
SpringSecurity-入门2-简单的用户授权_第2张图片
SpringSecurity-入门2-简单的用户授权_第3张图片
SpringSecurity-入门2-简单的用户授权_第4张图片
test 用户
SpringSecurity-入门2-简单的用户授权_第5张图片
SpringSecurity-入门2-简单的用户授权_第6张图片SpringSecurity-入门2-简单的用户授权_第7张图片
SpringSecurity-入门2-简单的用户授权_第8张图片
dev用户的截图
SpringSecurity-入门2-简单的用户授权_第9张图片
SpringSecurity-入门2-简单的用户授权_第10张图片
SpringSecurity-入门2-简单的用户授权_第11张图片
SpringSecurity-入门2-简单的用户授权_第12张图片

总结:通过配置的方式分配权限主要是使用这几个方法,antMatchers()mvcMatchers() ,这两个方法定义路径的,hasRole()hasAnyRole() 这两个方法设置权限。只要一一对应即可访问。
还有一对方法 hasAuthority()hasAnyAuthority 通过判断用户的 GrantedAuthority 来进行访问控制,底层跟 hasAnyRole() 差不多,我这里就不测试了。
权限开放的方法是 permitAll() , .antMatchers("/**").permitAll() 就表示所有的请求都可以通过,不需要验证
通过配置的方式一般是不用的,配置一般只配置一些静态的文件资源

b. 基于注解的对方法级别的授权

基于注解的方式有几个前提条件:

  1. 注释掉配置文件中的路由配置(url的权限配置)
  2. 开启全局的注解 @EnableGlobalMethodSecurity
  3. 选择使用的参数,共支持 prePostEnabled, securedEnabled,jsr250Enabled,proxyTargetClass 四种参数
  1. 使用 prePostEnabled
    使用 prePostEnabled 只用在注解上面开启 prePostEnabled 即可如:@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    //密码器
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin").password(passwordEncoder().encode("admin")).roles("test","admin")
                .and()
                .withUser("test").password(passwordEncoder().encode("test")).roles("test")
                .and()
                .withUser("dev").password(passwordEncoder().encode("dev")).roles("dev")
        ;
    }
    // 配置url的权限和授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .successForwardUrl("/index")
                ;
    }
}
  1. 使用 prePostEnabled 的话涉及到了四个注解 @PreAuthorize@PostAuthorize@PreFilter@PostFilter
  • PerAuthorize 它的作用就是在调用标记的方法之前,通过表达式来判定是否有权限访问。常用的方法有

    1. 基于角色的授权方式如:@PreAuthorize("hasAnyRole('admin')") ,表示标记的方法拥有admin角色才可以访问
    2. 基于UserDetails的表达式,例如 @PreAuthorize("hasAnyRole('admin') and principal.username.startsWith('adm')") 必须有 admin角色和用户名必须adm开头
    3. 基于对入参的 SpEL 表达式处理方法入参,例如:@PreAuthorize("#name.equals(principal.username)") 表示请求参数 name 必须与登录的用户命相同才能访问
  • PostAuthorize 它的作用跟 PerAuthorize 一样,只不过是在调用目标方法之后执行,如果方法没有返回值,那么相当于没有权限。

  • @PreFilter 它的验证过程发生在接口接收参数之前,对入参进行过滤,并且入参必须为java.utile.Collection ,你入参是一个集合,那么他就可以对这个集合里面的数据通过规则进行过滤。

  • @PreFilter 它的验证过程发生在接口处理好数据进行返回的时候,可以对返回的结果进行过滤。

    测试:

    @RestController
    @RequestMapping("/admin")
    public class AdminController {
        @GetMapping("/add")
        @PreAuthorize("hasAnyRole('admin') and principal.username.startsWith('adm')")
        public String add(){
            return this.getClass()+"添加的方法";
        }
        @PreAuthorize("#name.equals(principal.username)")
        @GetMapping("/update")
        public String update(String name){
            return this.getClass()+"更新的方法的方法";
        }
        @PreFilter(value = "filterObject.contains(principal.username)",filterTarget = "names")
    @GetMapping("/del")
    public String del(@RequestParam(value = "names") List<String> names){
        System.out.println(names);
        return this.getClass()+"删除方法执行成功";
    }
    }
    

预测结果:
1.用户admin可以访问 /admin/add
2.所有用户访问/admin/update?name=? 携带参数与登录用户名相同即可访问
3.用户dev,test无法访问/admin/add
测试:
1. admin
SpringSecurity-入门2-简单的用户授权_第13张图片
SpringSecurity-入门2-简单的用户授权_第14张图片
SpringSecurity-入门2-简单的用户授权_第15张图片
SpringSecurity-入门2-简单的用户授权_第16张图片
2. test 用户
SpringSecurity-入门2-简单的用户授权_第17张图片
SpringSecurity-入门2-简单的用户授权_第18张图片
SpringSecurity-入门2-简单的用户授权_第19张图片
SpringSecurity-入门2-简单的用户授权_第20张图片

总结:spring security 的认证方式有好几种,通常都是从数据库中读取角色来分配权限的,像配置和注解一般不使用,就像注解系统默认是关闭的,通过javaConfig来配置的一般只是一些静态的文件,但是我们现在的项目一般都是前后端分离和分布式的,一般也用不上配置,所以这些只用了解即可,所以一些测试我也没有做的那么全。

你可能感兴趣的:(spring,security,spring)