spring cloud各个服务间的接口都是暴露出去的,这样肯定不安全,一种简单的方式就是添加Basic auth,但这样zuul去请求就会要求输入这个用户名密码。
我原预想的应该在zuul本身应该是提供该配置项的,但我找了很久还是没找到,于是自己写一个玩玩。
这边先创建一个配置类:
@ConfigurationProperties("zuulSecurity")
public class BasicConfig {
private Map params = new LinkedHashMap<>();
public Map getParams() {
return params;
}
public void setParams(Map params) {
this.params = params;
}
}
以及BaiscParam类:
public class BasicParam {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
在META-INF中添加sping-configuration-metadata.json (这样做ide会有提示)
内容是:
{
"groups": [
{
"sourceType": "lew.bing.zuul.BasicConfig",
"name": "zuulSecurity.params",
"type": "java.util.Map"
}
]
}
添加配置项:
zuulSecurity:
params:
eureka-client-01:
username: username
password: password
然后就是filter
public class BasicHeadFilter extends ZuulFilter {
@Autowired
private BasicConfig basicConfig;
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
// 优先级在PreDecorationFilter之后
return 15;
}
@Override
public boolean shouldFilter() {
// 所有的都通过
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
String serviceId = (String) ctx.get(FilterConstants.SERVICE_ID_KEY);
if (serviceId != null) {
BasicParam basicParam = basicConfig.getParams().get(serviceId);
if (basicParam != null) {
String username = basicParam.getUsername();
String password = basicParam.getPassword();
byte[] token = Base64Utils.encode((username + ":" + password).getBytes());
ctx.addZuulRequestHeader("Authorization","Basic "+new String(token));
}
}
return null;
}
}
这边配置BasicConfig的params的key是服务的id,所以先要从ctx取出当前请求的service_id。
这里要说明一下,zuul有个内置的filter,PreDecorationFilter,顺序是5,这个过滤器才会给ctx添加SERVICE_ID,所以这个过滤器顺序必须要比5要大,不然就取不到SERVICE_ID。
剩下的就是在eureka-client-01的服务配置下basic,配置很简单:
security:
user:
name: username
password: password
需要加入依赖包spring-cloud-starter-security,这样如果直接请求这个服务下的接口就需要输入用户名密码,而通过zuul就不需要,可以让服务间的调用畅通无阻,但无法直接请求接口,防止信息泄露。
如下图:
当然这样的话,其他服务间调用也有记得加上Basic请求头,有空看看ribbon有没有简单的方式添加。