为了保护我们eureka注册中的安全我们需要限制ip和实例名称注册,eureka官方没有提供相关的配置,于是我们只能去扩展它的源码
1.创建一个CustomInstanceRegister 代码如下:
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.shared.Application;
import com.netflix.eureka.EurekaServerConfig;
import com.netflix.eureka.lease.Lease;
import com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl;
import com.netflix.eureka.resources.ServerCodecs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent;
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent;
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRenewedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class CustomInstanceRegister extends PeerAwareInstanceRegistryImpl implements ApplicationContextAware {
private ApplicationContext applicationContext;
private int defaultOpenForTrafficCount;
private List<String> allowedRegisteredIpAddress = new ArrayList<>();
private List<String> allowedRegisteredInstanceNames = new ArrayList<>();
public CustomInstanceRegister(EurekaServerConfig serverConfig, EurekaClientConfig clientConfig,
ServerCodecs serverCodecs, EurekaClient eurekaClient, int expectedNumberOfRenewsPerMin,
int defaultOpenForTrafficCount, List<String> allowedRegisteredIpAddress,
List<String> allowedRegisteredInstanceNames) {
super(serverConfig, clientConfig, serverCodecs, eurekaClient);
this.expectedNumberOfClientsSendingRenews = expectedNumberOfRenewsPerMin;
this.defaultOpenForTrafficCount = defaultOpenForTrafficCount;
this.allowedRegisteredIpAddress = allowedRegisteredIpAddress;
this.allowedRegisteredInstanceNames = allowedRegisteredInstanceNames;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public boolean cancel(String appName, String id, boolean isReplication) {
log.debug("注销的appName:{}, id:{}, isReplication{}", appName, id, isReplication);
pushEvent(new EurekaInstanceCanceledEvent(this, appName, id, isReplication));
return super.cancel(appName, id, isReplication);
}
@Override
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
super.openForTraffic(applicationInfoManager, count == 0 ? defaultOpenForTrafficCount : count);
}
@Override
public void register(InstanceInfo info, boolean isReplication) {
log.debug("注册地址:{}", info.getIPAddr());
printLogo(info);
pushEvent(new EurekaInstanceRegisteredEvent(this, info, resolveInstanceDuration(info),
isReplication));
String ip = info.getIPAddr();
if (!this.allowedRegisteredIpAddress.contains(ip)) {
log.debug("ip为【{}】的实例不允许注册", ip);
return;
}
if (!this.allowedRegisteredInstanceNames.contains(info.getAppName())) {
log.debug("实例名称为【{}】的实例不允许注册", info.getAppName());
return;
}
super.register(info, isReplication);
}
@Override
public void register(InstanceInfo info, int leaseDuration, boolean isReplication) {
log.debug("注册地址:{}", info.getIPAddr());
printLogo(info);
pushEvent(new EurekaInstanceRegisteredEvent(this, info, leaseDuration, isReplication));
String ip = info.getIPAddr();
if (!this.allowedRegisteredIpAddress.contains(ip)) {
log.debug("ip为【{}】的实例不允许注册", ip);
return;
}
if (!this.allowedRegisteredInstanceNames.contains(info.getAppName())) {
log.debug("实例名称为【{}】的实例不允许注册", info.getAppName());
return;
}
super.register(info, isReplication);
}
private void printLogo(InstanceInfo instanceInfo) {
log.debug("实例名称为:{},地址为:{}注册到注册中心", instanceInfo.getAppName(), instanceInfo.getIPAddr());
}
@Override
public boolean renew(String appName, String id, boolean isReplication) {
log.debug("appName:{},instanceId:{}", appName, id);
// 获取所有可以的相关服务实例
List<Application> applications = getSortedApplications();
applications.forEach(application -> {
if (application.getName().equals(appName)) {
InstanceInfo instanceInfo = null;
for (InstanceInfo info : application.getInstances()) {
if (info.getId().equals(id)) {
instanceInfo = info;
break;
}
}
// 发布重置事件
pushEvent(new EurekaInstanceRenewedEvent(this, appName, id, instanceInfo, isReplication));
}
});
return super.renew(appName, id, isReplication);
}
/**
* 唤醒事件
* @param event
*/
public void pushEvent(ApplicationEvent event) {
this.applicationContext.publishEvent(event);
}
private int resolveInstanceDuration(InstanceInfo info) {
int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS;
if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) {
leaseDuration = info.getLeaseInfo().getDurationInSecs();
}
return leaseDuration;
}
}
- 重写配置文件覆盖原本的InstanceRegistry
@Configuration
@EnableConfigurationProperties(CustomEurekaProperty.class)
public class CustomEurekaConfig {
@Autowired
private EurekaServerConfig eurekaServerConfig;
@Autowired
private EurekaClientConfig eurekaClientConfig;
@Autowired
@Qualifier(value = "eurekaClient")
private EurekaClient eurekaClient;
@Autowired
private CustomEurekaProperty property;
@Primary
@Bean(name = "customAwareInstanceRegistry")
public PeerAwareInstanceRegistry peerAwareInstanceRegistry(
ServerCodecs serverCodecs) {
this.eurekaClient.getApplications();
List<String> ips = new ArrayList<>();
String[] allowIps = StringUtils.split(property.getAllowIpAddr(), ",");
if (allowIps.length > 0) {
for (String ip : allowIps) {
ips.add(StringUtils.trim(ip));
}
}
List<String> instanceNames = new ArrayList<>();
String[] names = StringUtils.split(property.getAllowInstanceNames(), ",");
if (names.length > 0) {
for (String name : names) {
instanceNames.add(StringUtils.trim(name).toUpperCase());
}
}
return new CustomInstanceRegister(
this.eurekaServerConfig,
this.eurekaClientConfig,
serverCodecs,
this.eurekaClient,
this.property.getExpectedNumberOfRenewsPerMin(),
this.property.getDefaultOpenForTrafficCount(),
ips, instanceNames);
}
}
- 定义配置类
@Setter
@Getter
@ConfigurationProperties(prefix = "communal.eureka")
public class CustomEurekaProperty {
private String allowIpAddr = "127.0.0.1";
private int defaultOpenForTrafficCount = 1;
private int expectedNumberOfRenewsPerMin = 1;
private String allowInstanceNames = "flow-app-provider";
}