Ruoyi-Anonymous annotation@Anonymous analysis

1. Achieve bypassing permission authentication and directly access certain interfaces.
These parts can be written directly in the configuration in Spring Security, or you can release annotated methods or classes like this protagonist.
  Principle: Before spring security sets interception, obtain all requests with this annotation added, and add these requests to the configuration that releases interception.
2. Implementation
a) Add new annotations (the content in the annotations can be empty)

@Target({
    
    ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Anonymous {
    
    
}

b) When configuring spring security, obtain the annotated class or method

When annotations were used before, they were all in aspects, that is, when the program is executed and the annotations are added, the program can run the code in the aspects. Now we need to get all the request information after spring initializes the bean, and call afterPropertiesSet in spring's life cycle.

  RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
  Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();

Can be obtained. This logic is encapsulated in the tool class 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;
    }
}

c) Configure release interception

@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. Test

Currently, those that do not add anonymous annotations will be blocked and access will not be allowed.

4. Summary

Many public methods are implemented through annotations and aspects; combined with spring's life cycle functions, public logic processing is implemented. In many cases, it is processed by combining servlet and process capabilities with spring.

A lot of spring security configurations have been added to the code, as well as some related tool classes. framework.config.SecurityConfig is the core of Spring Security configuration. From this class, security extensions are configured. UserDetailsServiceImpl is a key class that implements authentication. There are many configurations and extensions of spring security. You need to understand the principles to sort out the common configuration content, but in short, it is to configure and extend the framework.

おすすめ

転載: blog.csdn.net/weixin_44749255/article/details/133923974