You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让@PropertySource访问受Spring Security保护的远程配置?

问题分析

你遇到的401错误,核心原因是**@PropertySource默认的资源加载逻辑不会自动解析URL中的user:xxx@格式认证信息并添加到请求头**,而curl会自动处理这种格式生成Basic认证头,所以curl能正常访问,而@PropertySource的请求没带认证信息,被Spring Security拦截返回401。

另外你提到的“默认无法访问子文件夹配置”是误解,Spring Cloud Config客户端原生支持拉取子目录下的配置,不需要手动用@PropertySource硬编码URL。

解决方案

方案一:改用Spring Cloud Config客户端原生配置(推荐)

这是Spring官方推荐的方式,无需手动处理认证和URL,客户端会自动传递认证信息到Config服务。

在客户端的bootstrap.yml(Spring Boot 3+可直接用application.yml)中添加以下配置:

spring:
  cloud:
    config:
      # Config服务地址
      uri: http://localhost:8888
      # Config服务的认证账号密码
      username: user
      password: xxx
      # 对应Config服务中配置仓库的应用名(即你之前的ConfigRepo)
      name: ConfigRepo
      # 环境profile
      profile: dev
      # Git分支/标签
      label: main
      # 拉取子目录下的额外配置文件
      additional-config-locations: "config:classpath:/db/database.properties"

客户端启动时会自动从Config服务拉取ConfigRepo-dev-main.properties以及db/database.properties的配置,且认证信息会被正确传递,不会出现401。

方案二:自定义PropertySourceFactory处理认证

如果你一定要用@PropertySource,可以自定义资源加载工厂,手动解析认证信息并添加到请求头:

  1. 编写自定义工厂类:
import org.springframework.core.io.EncodedResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.PropertySourceFactory;
import org.springframework.core.env.PropertySource;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class AuthenticatedHttpPropertySourceFactory implements PropertySourceFactory {
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        if (resource.getResource() instanceof UrlResource urlResource) {
            URL url = urlResource.getURL();
            String userInfo = url.getUserInfo();
            if (userInfo != null && userInfo.contains(":")) {
                String[] credentials = userInfo.split(":", 2);
                String authHeader = "Basic " + Base64.getEncoder().encodeToString((credentials[0] + ":" + credentials[1]).getBytes(StandardCharsets.UTF_8));
                
                // 创建带认证头的连接
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestProperty("Authorization", authHeader);
                
                // 包装资源,返回带认证的连接
                Resource authenticatedResource = new UrlResource(url) {
                    @Override
                    public URLConnection getURLConnection() throws IOException {
                        return connection;
                    }
                };
                return new DefaultPropertySourceFactory().createPropertySource(name, new EncodedResource(authenticatedResource));
            }
        }
        return new DefaultPropertySourceFactory().createPropertySource(name, resource);
    }
}
  1. 在@PropertySource中指定该工厂:
@PropertySource(
    value = "http://user:xxx@localhost:8888/ConfigRepo/dev/main/db/database.properties",
    ignoreResourceNotFound = true,
    factory = AuthenticatedHttpPropertySourceFactory.class
)

这样@PropertySource会通过自定义工厂添加Basic认证头,就能正常访问Config服务的受保护资源。

额外注意点

你的Config服务Spring Security配置中,antMatchers("/ConfigRepo").permitAll()只放行精确匹配/ConfigRepo的请求,而实际请求的是/ConfigRepo/dev/main/...这类子路径,这些请求会被要求认证,这是正确的配置——只要请求带正确的认证头就能正常访问。

内容的提问来源于stack exchange,提问作者user3593261

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:13:25