若依
1、实现绕过权限认证,可以直接访问某些接口。
这些部分可以直接在Spring Security中的配置去写,也可以像这个主角这样给添加了注解的方法或类进行放行。
原理:在spring security设置拦截前,获取到所有添加了该注解的请求,把这些请求添加到放开拦截的配置中。
2、实现
a)新增注解(注解中内容是可以空的)
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Anonymous {
}
b)在spring security进行配置的时候,获取到添加了注解的类或方法
之前使用注解的时候都是在切面中,也就是当程序执行到添加了注解时程序能运行到切面里的代码。现在要在spring初始化bean后获取到全部的请求信息,在spring的生命周期 afterPropertiesSet时 通过调用
RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
可以获取到。这个逻辑封装到了工具类 PermitAllUrlProperties中。
@Configuration
public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware {/*** 正则表达式 匹配path variable* 如: @GetMapping(value = "/configKey/{configKey}") 进行匹配后替换为/configKey/***/private static final Pattern PATTERN = Patternpile("\\{(.*?)\\}");/*** spring 上下文* 从中可以获取到各种bean*/private ApplicationContext applicationContext;/*** 该集合中保存了全部标记过匿名注解的url请求*/private List<String> urls = new ArrayList<>();public String ASTERISK = "*";@Overridepublic void afterPropertiesSet() {// 获取全部的handlerMappingsRequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();map.keySet().forEach(info->{HandlerMethod handlerMethod = map.get(info);// 获取方法上的注解 替代path variable 为 *Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);Optional.ofNullable(method).ifPresent(anonymous->info.getPatternsCondition().getPatterns().forEach(url->urls.add(RegExUtils.replaceAll(url,PATTERN,ASTERISK))));// 获取类上的注解Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);Optional.ofNullable(controller).ifPresent(anonymous->info.getPatternsCondition().getPatterns().forEach(url->urls.add(RegExUtils.replaceAll(url,PATTERN,ASTERISK))));});}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public List<String> getUrls() {return urls;}public void setUrls(List<String> urls) {this.urls = urls;}
}
c)配置放开拦截
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {...@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {// 注解标记允许匿名访问的urlExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());... 其他配置}
3、 测试
目前对于没有添加匿名注解的都会拦截不允许访问。
4、总结
公共的方法很多都是通过注解、切面进行实现的;结合spring的生命周期函数,实现公共逻辑的处理。很多时候是结合了servlet和过程和spring的能力进行处理的。
代码中添加了很多spring security的配置,以及涉及到的一些工具类。framework.config.SecurityConfig是Spring Security的配置的核心,从这个类会把对security的扩展配置进去的。UserDetailsServiceImpl是重点类,实现认证过的关键类。spring security的配置和扩展很多,需要理解下原理去梳理下常见的配置内容,但是总之就是去配置和扩展框架。
发布者:admin,转转请注明出处:http://www.yc00.com/web/1703355330a1291994.html
评论列表(0条)