SpringSecurity请求授权规则配置与注解使用说明

简介: SpringSecurity请求授权规则配置与注解使用说明

【1】请求授权规则配置

这里主要是重写WebSecurityConfigurerAdapter 的configure方法。

protected void configure(HttpSecurity http) throws Exception {
     this.logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");
     ((HttpSecurity)((HttpSecurity)((AuthorizedUrl)http.
       authorizeRequests()
       .anyRequest())
       .authenticated()
       .and())
       .formLogin()
       .and())
       .httpBasic();
 }

① 自定义登录

这里UsernamePasswordAuthenticationFilter 将起作用。

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.formLogin()
            .loginPage("/login.html") //登录页面
            .loginProcessingUrl("/user/login") // 默认处理登录的请求
            .successForwardUrl("/success")  //登录成功后跳转到哪个URL
            .defaultSuccessUrl("/index",true)// 登录成功后跳转路径
            .failureForwardUrl("/fail") //登录失败后跳转到哪个URL
            .permitAll();
}

这里successForwardUrl与defaultSuccessUrl 都可以实现认证成功后跳转的效果,不过具体用法上有所区别。通常建议使用defaultSuccessUrl,至于具体区别后面另开章节学习。


还可以修改用户名和密码的key(默认是username 和password):

.usernameParameter("userName")  //自定义获取用户登录名
.passwordParameter("password")  //自定义获取用户登录密码

② 设置放行与需要认证的请求

 http.authorizeRequests()
               .antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行
               .permitAll()//匹配上述请求的直接放行
               .anyRequest().authenticated();//其他请求都需要认证

③ 基于角色或权限进行访问控制

回顾上文我们自定义实现类设置用户角色权限如下:


这里用户角色、权限是指定的,那么我们是不是可以升级一下从数据库查询呢?如下图所示:

① hasAuthority 方法


如果当前的主体具有指定的权限,则返回 true,否则返回false。

http.authorizeRequests()
     .antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行
     .permitAll()
     .antMatchers("/findAll").hasAuthority("admin") // 用户访问findAll 必须有 admin 权限
     .anyRequest().authenticated();//其他请求都需要认证


② hasAnyAuthority方法

如果当前的主体有任何提供的角色(给定的作为一个逗号分隔的字符串列表)的话,返回true。

http.authorizeRequests()
    .antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行
    .permitAll()
    .antMatchers("/findAll").hasAuthority("admin") // 用户访问findAll 必须有 admin 权限
    .antMatchers("/find").hasAnyAuthority("admin","sale") // 用户访问 find ,拥有admin或者sale之一即可
    .anyRequest().authenticated();//其他请求都需要认证


③ hasRole 方法

如果用户具备给定角色就允许访问,否则出现403。如果当前主体具有指定的角色,则返回true。

这里需要说明的是在SpringSecurity源码中对hasRole 进行了处理,为角色名自动添加上了ROLE_前缀。故我们配置的时候不加该前缀即可。


org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer#hasRole

http.authorizeRequests()
     .antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行
     .permitAll()
     .antMatchers("/findAll").hasAuthority("admin") // 用户访问findAll 必须有 admin 权限
     .antMatchers("/find").hasAnyAuthority("admin","sale") // 用户访问 find ,拥有admin或者sale之一即可
     .antMatchers("/sale/**").hasRole("sale") // 需要用户具有sale角色
     .anyRequest().authenticated();//其他请求都需要认证

④ hasAnyRole方法

表示用户具备任何一个条件都可以访问。

http.authorizeRequests()
     .antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行
     .permitAll()
     .antMatchers("/findAll").hasAuthority("admin") // 用户访问findAll 必须有 admin 权限
     .antMatchers("/find").hasAnyAuthority("admin","sale") // 用户访问 find ,拥有admin或者sale之一即可
     .antMatchers("/sale/**").hasRole("sale") // 需要用户具有sale角色
     .antMatchers("/product/**").hasAnyRole("admin","product") //用户具有admin或者product角色之一即可
     .anyRequest().authenticated();//其他请求都需要认证

④ 自定义403访问拒绝页面

修改配置类

http.exceptionHandling().accessDeniedPage("/unauth.html");

这里需要说明的是你的静态资源文件路径下比如static下需要有unauth.html页面,当然这里也可以换成一个请求如/unauth,编写controller来处理该请求。

⑤ 自定义退出


修改配置类如下:

http.logout().logoutUrl("/logout")  //退出登录请求
      .logoutSuccessUrl("/index") //注销成功后跳转地址
      .permitAll();

还可以指定在退出时删除某些cookie、注销会话:

.deleteCookies("remember-me","sign")
.invalidateHttpSession(true)

【2】SpringSecurity的注解

通过方法上的注解我们可以实现在后端服务上细粒度的权限校验。主启动类上要添加@EnableGlobalMethodSecurity注解

@SpringBootApplication
@MapperScan("com.jane.mapper")
@EnableGlobalMethodSecurity(securedEnabled=true,prePostEnabled = true)
public class Securitydemo1Application {
    public static void main(String[] args) {
        SpringApplication.run(Securitydemo1Application.class, args);
    }
}

① @Secured

判断是否具有角色,另外需要注意的是这里匹配的字符串需要添加前缀“ROLE_“ 。使用该注解前要先开启注解支持:@EnableGlobalMethodSecurity(securedEnabled=true)

// 测试注解: 
@RequestMapping("testSecured") 
@ResponseBody 
@Secured({"ROLE_normal","ROLE_admin"}) 
public String helloUser() { 
  return "hello,user"; 
}

② @PreAuthorize

先开启注解功能: @EnableGlobalMethodSecurity(prePostEnabled = true)

@PreAuthorize注解适合进入方法前的权限验证,是一种常见的应用策略。

@RequestMapping("/preAuthorize") 
@ResponseBody 
//@PreAuthorize("hasRole('ROLE_admin')") 
@PreAuthorize("hasAnyAuthority('menu:system')") 
public String preAuthorize(){ 
  System.out.println("preAuthorize"); 
  return "preAuthorize"; 
}

可以看到这里权限表达式中可以使用hasRole、hasAnyRole、hasAuthority 以及hasAnyAuthority来灵活控制。


③ @PostAuthorize

先开启注解功能: @EnableGlobalMethodSecurity(prePostEnabled = true) 。@PostAuthorize 注解很少使用,在方法执行后再进行权限验证,适合验证带有返回值的权限。

@RequestMapping("/testPostAuthorize") 
@ResponseBody 
@PostAuthorize("hasAnyAuthority('menu:system')") 
public String preAuthorize(){ 
  System.out.println("test--PostAuthorize"); 
  return "PostAuthorize"; 
}

④ @PostFilter

@PostFilter :权限验证之后对数据进行过滤。表达式中的 filterObject 引用的是方法返回值List中的某一个元素。通常也很少使用。


如下留下用户名是admin1的数据:

@RequestMapping("getAll") 
@PreAuthorize("hasRole('ROLE_admin')") 
@PostFilter("filterObject.username == 'admin1'") 
@ResponseBody public List<UserInfo> getAllUser(){ 
  ArrayList<UserInfo> list = new ArrayList<>(); 
  list.add(new UserInfo(1l,"admin1","6666")); 
  list.add(new UserInfo(2l,"admin2","888")); 
  return list; 
}

⑤ @PreFilter

@PreFilter: 进入控制器之前对数据进行过滤。

@RequestMapping("getTestPreFilter") 
@PreAuthorize("hasRole('ROLE_admin')") 
@PreFilter(value = "filterObject.id%2==0") 
@ResponseBody public List<UserInfo> getTestPreFilter(@RequestBody List<UserInfo> list){ 
  list.forEach(t-> { System.out.println(t.getId()+"\t"+t.getUsername()); }); 
  return list; 
}

综上,这里我们常使用@Secured@PreAuthorize两个注解在进入方法前进行角色、权限的控制。进入方法前数据的过滤@PreFilter注解偶尔会看到,至于方法执行完后进行校验的两个注解@PostAuthorize@PostFilter几乎不用。

目录
相关文章
|
安全 NoSQL Java
SpringBoot3整合SpringSecurity,实现自定义接口权限过滤(二)
SpringBoot3整合SpringSecurity,实现自定义接口权限过滤
990 0
|
7月前
|
安全 Java 开发者
Spring Security自定义认证异常和授权异常
Spring Security自定义认证异常和授权异常
370 4
|
7月前
|
JSON 安全 关系型数据库
SpringCloud Gateway 实现自定义全局过滤器 + JWT权限验证
SpringCloud Gateway 实现自定义全局过滤器 + JWT权限验证
|
安全
springsecurity配置类以及授权逻辑的编写
springsecurity配置类以及授权逻辑的编写
101 0
|
安全 Java 数据库连接
四.SpringSecurity基础-自定义登录流程
SpringSecurity基础-自定义登录流程
|
SQL 安全 Java
SpringBoot 整合SpringSecurity示例实现前后分离权限注解+JWT登录认证
SpringSecurity是一个用于Java 企业级应用程序的安全框架,主要包含用户认证和用户授权两个方面.相比较Shiro而言,Security功能更加的强大,它可以很容易地扩展以满足更多安全控制方面的需求,但也相对它的学习成本会更高,两种框架各有利弊.实际开发中还是要根据业务和项目的需求来决定使用哪一种.
SpringBoot 整合SpringSecurity示例实现前后分离权限注解+JWT登录认证
|
前端开发 JavaScript Java
SpringBoot 统一功能处理:用户登录权限校验-拦截器、异常处理、数据格式返回
本篇将要学习 Spring Boot 统一功能处理模块,这也是 AOP 的实战环节 用户登录权限的校验实现接口 HandlerInterceptor + WebMvcConfigurer 异常处理使用注解 @RestControllerAdvice + @ExceptionHandler 数据格式返回使用注解 @ControllerAdvice 并且实现接口 @ResponseBodyAdvice
718 0
|
存储 缓存 安全
SpringBoot3整合SpringSecurity,实现自定义接口权限过滤(一)
SpringBoot3整合SpringSecurity,实现自定义接口权限过滤
984 0
|
消息中间件 JavaScript 小程序
SpringBoot 统一功能处理:用户登录权限校验-拦截器、异常处理、数据格式返回 下
SpringBoot 统一功能处理:用户登录权限校验-拦截器、异常处理、数据格式返回 下
SpringBoot 统一功能处理:用户登录权限校验-拦截器、异常处理、数据格式返回 下
|
前端开发 Java 数据库
SpringBoot分组校验及自定义校验注解
在日常的开发中,参数校验是非常重要的一个环节,严格参数校验会减少很多出bug的概率,增加接口的安全性。在此之前写过一篇SpringBoot统一参数校验主要介绍了一些简单的校验方法。而这篇则是介绍一些进阶的校验方式。比如说:在某个接口编写的过程中肯定会遇到,当xxType值为A,paramA值必传。xxType值为B,paramB值必须传。对于这样的,通常的做法就是在controller加上各种if判断。显然这样的代码是不够优雅的,而分组校验及自定义参数校验,就是来解决这个问题的。