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 = Pattern.compile("\\{(.*?)\\}"); /** * spring 上下文 * 从中可以获取到各种bean */ private ApplicationContext applicationContext; /** * 该集合中保存了全部标记过匿名注解的url请求 */ private List<String> urls = new ArrayList<>(); public String ASTERISK = "*"; @Override public void afterPropertiesSet() { // 获取全部的handlerMappings RequestMappingHandlerMapping 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)))); }); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public List<String> getUrls() { return urls; } public void setUrls(List<String> urls) { this.urls = urls; } }PermitAllUrlProperties 工具类
c)配置放开拦截
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { ... @Override protected void configure(HttpSecurity httpSecurity) throws Exception { // 注解标记允许匿名访问的url ExpressionUrlAuthorizationConfigurer<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的配置和扩展很多,需要理解下原理去梳理下常见的配置内容,但是总之就是去配置和扩展框架。
代码地址:https://github.com/hunji/RYMirror/releases/tag/2.5%E5%8C%BF%E5%90%8D%E6%B3%A8%E8%A7%A3--SpringSecurity
UserDetailsServiceImpl标签:urls,一步,--,spring,url,Anonymous,注解,public From: https://www.cnblogs.com/hunji-fight/p/17606433.html