Anonymous注解 允许 匿名访问不鉴权



前言

这个值得一看,好像还可以拿到其他项目直接用


一、Anonymous定义

package com.ruoyi.common.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 匿名访问不鉴权注解
 *
 * @author ruoyi
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Anonymous {
}

二、注解配置

package com.ruoyi.framework.config.properties;

import java.util.*;
import java.util.regex.Pattern;
import org.apache.commons.lang3.RegExUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import com.ruoyi.common.annotation.Anonymous;

/**
 * 设置Anonymous注解 允许 匿名访问不鉴权
 * 项目初始化时候,会将Anonymous注解的 路径 提取出来,放到urls里面
 *
 * InitializingBean:为bean提供了初始化方法的方式,凡是继承该接口的类,在初始化bean的时候都会执行afterPropertiesSet方法
 *
 * ApplicationContextAware:当一个类实现了这个接口之后,这个类就可以方便的获得ApplicationContext对象(spring上下文)
 * ,Spring发现某个Bean实现了ApplicationContextAware接口,Spring容器会在创建该Bean之后,自动调用该Bean的setApplicationContext(参数)方法
 * ,调用该方法时,会将容器本身ApplicationContext对象作为参数传递给该方法。
 *
 * @author ruoyi
 */
@Configuration
public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware {
    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");

    // spring上下文
    private ApplicationContext applicationContext;

    // 前端请求接口的时候,如果在这个url里面,直接放行
    private List<String> urls = new ArrayList<>();

    // 替代字符串
    public String ASTERISK = "*";

    @Override
    public void afterPropertiesSet() {

        // 将整个项目所有bean都拿出来
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);

        // 获取 每个url 与 方法、类的对应关系
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();

        // info 是代表每个url对象
        map.keySet().forEach(info -> {
             // 获取类和方法的信息
            HandlerMethod handlerMethod = map.get(info);

            // 获取方法上边的注解,如果此方法被“Anonymous”注解,则返回该方法,否则返回null
            Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
            // method为null啥也不干,否则替代path variable 为 *
            Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));

            // 获取类上边的注解,如果此类被“Anonymous”注解,则返回该类,否则返回null
            Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
            // controller为null啥也不干,否则替代path variable 为 *
            Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
        });
    }

    /**
     * @Description // 这玩意是接口ApplicationContextAware带来的,就是为了在本类中方便获取 applicationContext
     * @Date 16:15 2023/3/22
     **/
    
    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.applicationContext = context;
    }

    public List<String> getUrls() {
        return urls;
    }

    public void setUrls(List<String> urls) {
        this.urls = urls;
    }
}

三、Debug讲解

1、看看根据上下文获取到的是个啥,这个是获取到所有接口的 【访问路径:接口地址路径】
在这里插入图片描述
2、遍历获取每个路径的方法
在这里插入图片描述
3、判断当前方法有没有Anonymous注解哇
在这里插入图片描述
在这里插入图片描述
4、被Anonymous注解修饰的,将根据正则替换 链接字符串
在这里插入图片描述
5、最后 Security配置类中把 urls 中的访问地址给全部放行
在这里插入图片描述


总结

说不定会用的到,记录一下
Logo

快速构建 Web 应用程序

更多推荐