在实际项目中使用到了springsecurity作为安全框架,我们会遇到需要放行一些接口,使其能匿名访问的业务需求。 但是每当需要当需要放行时,都需要在security的配置类中进行修改,感觉非常的不优雅。
例如这样:
图片
所以想通过自定义一个注解,来进行接口匿名访问。在实现需求前,我们先了解一下security的两种方行思路。
第一种就是在 configure(WebSecurity web)
方法中配置放行,像下面这样:
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", "/js/**", "/index.html", "/img/**", "/fonts/**", "/favicon.ico", "/verifyCode");
}
第二种方式是在 configure(HttpSecurity http)
方法中进行配置:
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{
httpSecurity
.authorizeRequests()
.antMatchers("/hello").permitAll()
.anyRequest().authenticated()
}
两种方式最大的区别在于,第一种方式是不走 Spring Security 过滤器链,而第二种方式走 Spring Security 过滤器链,在过滤器链中,给请求放行。如果您正在学习Spring Boot,那么推荐一个连载多年还在继续更新的免费教程:http://blog.didispace.com/spring-boot-learning-2x/
在我们使用 Spring Security 的时候,有的资源可以使用第一种方式额外放行,不需要验证,例如前端页面的静态资源,就可以按照第一种方式配置放行。
有的资源放行,则必须使用第二种方式,例如登录接口。大家知道,登录接口也是必须要暴露出来的,不需要登录就能访问到的,但是我们却不能将登录接口用第一种方式暴露出来,登录请求必须要走 Spring Security 过滤器链,因为在这个过程中,还有其他事情要做,具体的登录流程想了解的可以自行百度。
了解完了security的两种放行策略后,我们开始实现
首先创建一个自定义注解
@Target({ElementType.METHOD}) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented //生成文档
public @interface IgnoreAuth {
}
这里说明一下, @Target({ElementType.METHOD})
我的实现方式,注解只能标记在带有 @RequestMapping
注解的方法上。具体为什么下面的实现方式看完就懂了。
接下来创建一个security的配置类SecurityConfig并继承 WebSecurityConfigurerAdapter
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping;
/**
* @ description: 使用这种方式放行的接口,不走 Spring Security 过滤器链,
* 无法通过 SecurityContextHolder 获取到登录用户信息的,
* 因为它一开始没经