Springboot集成security,自定义@Anonymous标签实现免登录,免鉴权

        首先,项目springboot使用了2.6.8版本,集成security的过程中,使用了比较严格的自定义策略,任何请求都需要认证和授权,判断用户是否有查询改接口的权限。并且提供了配置或者注解两种方式提供匿名访问的接口。

 第一种通过配置

 第二种使用自定义注解

 自己实现

AccessDecisionManager

FilterInvocationSecurityMetadataSource

 引起需要收集@Anonymous注解标注的controller。

于是就像参照spring启动扫描注解的方式实现,然后自定义了

 参照spring scan

/**
 * 参照spring scan
 * @author: Barry.Yu
 * @date: 2022/9/30
 * @desc: 自定义匿名访问扫描类
 **/
@Slf4j
public class AnonymousScanRegistrar  implements EnvironmentCapable, ImportBeanDefinitionRegistrar {

    private static final String anonymousBeanName = "anonymousUrlServiceImpl";


    private Set<String> anonymousUrls = new HashSet<>();

    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";

    private String resourcePattern = DEFAULT_RESOURCE_PATTERN;

    @Nullable
    private Environment environment;

    @Nullable
    private ResourcePatternResolver resourcePatternResolver;

    @Nullable
    private MetadataReaderFactory metadataReaderFactory;


    private final Map<String, Function<Method,String[]>> functionMap = new HashMap<>();

    {
        functionMap.put("org.springframework.web.bind.annotation.PostMapping",this::postFunction);
        functionMap.put("org.springframework.web.bind.annotation.PutMapping",this::putFunction);
        functionMap.put("org.springframework.web.bind.annotation.GetMapping",this::getFunction);
        functionMap.put("org.springframework.web.bind.annotation.DeleteMapping",this::delFunction);
        functionMap.put("org.springframework.web.bind.annotation.RequestMapping",this::requestFunction);
    }


    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry){
        AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(annotationMetadata.getAnnotationAttributes(AnonymousScan.class.getName()));
        String[] basePackages = annoAttrs.getStringArray("basePackage");
        for (String basePackage : basePackages) {
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    resolveBasePackage(basePackage) + '/' + this.resourcePattern;
            try {
                Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
                for (Resource resource : resources) {
                    MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                    createUrls(metadataReader.getClassMetadata().getClassName());
                }
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
                AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
                //beanDefinition的beanClass
                beanDefinition.setBeanClass(AnonymousUrlServiceImpl.class);
                ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
                constructorArgumentValues.addIndexedArgumentValue(0, anonymousUrls);
                registry.registerBeanDefinition(anonymousBeanName, beanDefinition);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    /**
     * 构建所需要的匿名路径
     * @param beanClassName
     */
    private void createUrls(String beanClassName){
        try {
            Class aClass = Class.forName(beanClassName);
            RequestMapping requestMapping = (RequestMapping) aClass.getAnnotation(RequestMapping.class);
            if(requestMapping!=null){
                String[] pathParents = requestMapping.value();
                String[] paths = null;
                Method[] methods = aClass.getMethods();
                for (Method method : methods) {
                    Anonymous anonymous = method.getAnnotation(Anonymous.class);
                    if(anonymous!=null){
                        Annotation[] annotations = method.getAnnotations();
                        for (Annotation annotation : annotations) {
                            Function<Method, String[]> methodFunction = functionMap.get(annotation.annotationType().getName());
                            if(methodFunction!=null){
                                paths = methodFunction.apply(method);
                                break;
                            }
                        }
                        if(paths!=null && paths.length>0){
                            for (String pathParent : pathParents) {
                                for (String path : paths) {
                                    anonymousUrls.add( pathParent +  path);
                                }
                            }
                        }
                        paths = null;
                    }
                }
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }


    }

    private  String[] postFunction(Method method){
        return method.getAnnotation(PostMapping.class).value();
    }
    private  String[] getFunction(Method method){
        return method.getAnnotation(GetMapping.class).value();
    }
    private  String[] putFunction(Method method){
        return method.getAnnotation(PutMapping.class).value();
    }
    private  String[] delFunction(Method method){
        return method.getAnnotation(DeleteMapping.class).value();
    }
    private  String[] requestFunction(Method method){
        return method.getAnnotation(RequestMapping.class).value();
    }



    public final MetadataReaderFactory getMetadataReaderFactory() {
        if (this.metadataReaderFactory == null) {
            this.metadataReaderFactory = new CachingMetadataReaderFactory();
        }
        return this.metadataReaderFactory;
    }

    private ResourcePatternResolver getResourcePatternResolver() {
        if (this.resourcePatternResolver == null) {
            this.resourcePatternResolver = new PathMatchingResourcePatternResolver();
        }
        return this.resourcePatternResolver;
    }

    protected String resolveBasePackage(String basePackage) {
        return ClassUtils.convertClassNameToResourcePath(getEnvironment().resolveRequiredPlaceholders(basePackage));
    }

    @Override
    public Environment getEnvironment() {
        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }
        return this.environment;
    }

    public Set<String> getAnonymousUrls(){
        return anonymousUrls;
    }
}

启动类上加上

猜你喜欢

转载自blog.csdn.net/evil_lrn/article/details/129066089