个人博客:https://everspring.github.io/
公众号:爱历史的IT男
代码样例为:SpringCloud 1.5.22
Eureka,Gitlab为配置中心仓库
在SpringCloud工程中,有些时候需要检查服务真正获取到的配置。因为代码仓库中的不一定是服务真实加载的。
http://127.0.0.1:8770
,客户端服务是service-a
,profile默认,即访问http://127.0.0.1:8770/service-a
即可获取。HTTP访问的格式如下(也是访问的优先级):/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
配置了用户名和密码
config server的配置如下:
spring:
application:
name: config-server
security:
user:
name: test # HTTP访问配置中心时的用户名和密码
password: test-pwd
cloud:
config:
server:
git:
uri: http://gitlab.test.com/config-server.git
username: git-user #仓库的用户名密码
password: git-pwd
default-label: dev
服务端的配置如下:
spring:
application:
name: service-a
cloud:
config:
discovery:
enabled: true
serviceId: config-server
fail-fast: true
username: test # !!!这里和config server配置的一致
password: test-pwd
这种加了密的访问方式有两种:
这种适合知道用户名、密码的情况,使用方式,请求地址中加入用户名、密码,http://用户名:密码@ip:端口/服务名/xxxx,比如:
curl http://test:[email protected]:8770/service-a
实现代码解析(下面版本是SpringCloud 1.5.22源码):
org.springframework.cloud.config.client.ConfigServicePropertySourceLocator#getSecureRestTemplate
private RestTemplate getSecureRestTemplate(ConfigClientProperties client) {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setReadTimeout((60 * 1000 * 3) + 5000); //TODO 3m5s, make configurable?
RestTemplate template = new RestTemplate(requestFactory);
# 这里就是重点
String username = client.getUsername();
String password = client.getPassword();
String authorization = client.getAuthorization();
Map headers = new HashMap<>(client.getHeaders());
if (password != null && authorization != null) {
throw new IllegalStateException(
"You must set either 'password' or 'authorization'");
}
if (password != null) {
byte[] token = Base64Utils.encode((username + ":" + password).getBytes());
headers.put("Authorization", "Basic " + new String(token));
}
else if (authorization != null) {
headers.put("Authorization", authorization);
}
if (!headers.isEmpty()) {
template.setInterceptors(Arrays. asList(
new GenericRequestHeaderInterceptor(headers)));
}
return template;
}
org.springframework.cloud.config.client.ConfigClientProperties#extractCredentials
private Credentials extractCredentials() {
Credentials result = new Credentials();
String uri = this.uri;
result.uri = uri;
Credentials explicitCredentials = getUsernamePassword();
result.username = explicitCredentials.username;
result.password = explicitCredentials.password;
try {
URL url = new URL(uri);
# 此处获取用户名、密码
String userInfo = url.getUserInfo();
// no credentials in url, return explicit credentials
if (StringUtils.isEmpty(userInfo) || ":".equals(userInfo)) {
return result;
}
}
如果无法知道用户名、密码,可以让运维人员提供token,生成token的代码样例就是上方第一个代码样例中的
byte[] token = Base64Utils.encode((username + ":" + password).getBytes());
headers.put("Authorization", "Basic " + new String(token));
请求中将header加入Authorization
,值为Basic token的值
,假如生成的token为xxxxxx,请求如下:
curl "http://127.0.0.1:8770/service-a" -H "Authorization: Basic xxxxxx"