小心,别被eureka坑了
Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。
Eureka包含两个组件:Eureka Server和Eureka Client。具体怎么部署这里就不说了,直接说问题
Eureka 客户端注册时需要配置服务端地址,类似如下配置
eureka:
instance:
hostname: hello-service
prefer-ip-address: true
instance-id: ${eureka.instance.hostname}:${server.port}
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: "http://localhost:8761/eureka/"
这种配置后客户端就会注册到Eureka注册中心,在Eureka界面就能看到:
但是这样把界面暴露到外面,会把注册信息泄漏,一般公司也不允许暴露没有安全认证的后台界面
所以尝试把Eureka界面加密
引入security
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Eureka服务端增加basic鉴权:
spring:
application:
name: eureka-server
security:
basic:
enabled: true
user:
name: admin
password: 123456
配置完成后发现现在访问eureka界面需要用户名和密码登录了
但是登录进去后发现刚才的hello服务并没有注册进来
呕吼,应该是客户端没配置鉴权信息的原因,在官网找到了客户端鉴权配置方式
https://cloud.spring.io/spring-cloud-netflix/multi/multi__service_discovery_eureka_clients.html
于是在hello服务修改配置如下:
eureka:
instance:
hostname: hello-service
prefer-ip-address: true
instance-id: ${eureka.instance.hostname}:${server.port}
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://admin:123456@localhost:8761/eureka/
重启hello服务后,发现还是没有注册成功,原来增加basic验证后,不支持跨域访问了,我的天,你这个大坑,服务注册肯定是跨域的了,
于是,迅速增加配置,去掉跨域拦截
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.csrf().disable();//一种方式直接关闭csrf,另一种配置url后放行
http.csrf().ignoringAntMatchers("/eureka/**");
super.configure(http);
}
}
终于在界面看到可可爱爱的hello服务了,但是呢,还有一个问题,现在不允许这种明文密码出现在配置或代码中,怎么办呢?
首先想到的就是密码加密, 所以从spring-securiry中找到PasswordEncoderFactories加密
PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("123456")
然后把加密后的结果放到Eureka服务端配置文件中:
security:
basic:
enabled: true
user:
name: admin
password: '{bcrypt}$2a$10$mhH7ogkRB91YDUO3F883JugDMHz2o6miT95.8ukqEc6Ed4Z2xyHmm' //必须有引号
那Eureka客户端怎么办? 同样道理的嘛
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://admin:{bcrypt}$2a$10$mhH7ogkRB91YDUO3F883JugDMHz2o6miT95.8ukqEc6Ed4Z2xyHmm@localhost:8761/eureka/
但是呢,启动直接报错,害,eureka注册时并不会解密
解析Eureka服务端地址失败,即使是加上引号也是报相同错误
Eureka客户端注册过来的消息,服务端并不会给解密,那怎么办呢?
从上图可以看到如果要实现更复杂的需求,需要通过注入clientFilter方式,so,搞起来
@Configuration
@Priority(Integer.MIN_VALUE)
public class UserCilentFilter extends ClientFilter {
@Override
public ClientResponse handle(ClientRequest clientRequest) throws ClientHandlerException {
try {
String originUrl = clientRequest.getURI().toString();
if(originUrl.contains("@")){
return this.getNext().handle(clientRequest);
}
String userNameAndPwd = "http://admin"+ jiemi("'{bcrypt}$2a$10$mhH7ogkRB91YDUO3F883JugDMHz2o6miT95.8ukqEc6Ed4Z2xyHmm'");
String addUserInfoUrl = originUrl.replaceFirst("http://", userNameAndPwd);
clientRequest.setURI(new URI(addUserInfoUrl));
} catch (URISyntaxException e) {
// FIXME: 2021/4/2
}
return this.getNext().handle(clientRequest);
}
private String jiemi(String pwd) {
// FIXME: 解密
return pwd;
}
@Bean
public DiscoveryClient.DiscoveryClientOptionalArgs discoveryClientOptionalArgs() {
DiscoveryClient.DiscoveryClientOptionalArgs discoveryClientOptionalArgs = new DiscoveryClient.DiscoveryClientOptionalArgs();
discoveryClientOptionalArgs.setAdditionalFilters(Collections.singletonList(new UserCilentFilter()));
return discoveryClientOptionalArgs;
}
}
这样写的思路是让其他客户端注册时去掉用户名和密码,然后在自定义过滤器中对没有用户名和密码时补充上basic验证的用户名和密码
然后开始测试,这样还是不行,其他服务注册过来时,会被其他安全过滤器拦截都走不到自定义的拦截器就返回鉴权失败了,即使@Priority(Integer.MIN_VALUE)最高优先级
那是不是可以在更前面的地方进行拦截呢?增加ServletRequest拦截器可行否?
@Configuration
public class ServerRequestAuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
//业务实现,根据请求的IP或者参数判断是否可以执行注册或者访问
// String addUserInfoUrl = originUrl.replaceFirst("http://", "http://admin:123456@");
filterChain.doFilter(request, response);
}
}
但是假设这样修改后,登录的web界面也会走到这个拦截器,同样会增加鉴权
也就是说这样直接增加鉴权,无法区分是其他客户端注册还是从界面访问
也没有什么太好的办法了,就直接在security的拦截器中把eureka注册相关的放掉,不进行鉴权操作
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/eureka/**").permitAll();
super.configure(http);
}
这样设置后除了直接访问的界面需要鉴权外,其他eureka相关注册、查询等不需要鉴权
都这样分层鉴权操作了,再找下是不是有其他方式达到相同的目的,于是找到
eureka:
dashboard:
enabled: false
通过在启动脚本设置后,效果是类似的,在eureka主界面无法访问
上面所有的操作都是为了信息安全考虑,还有一个经常忘记需要考虑的组件是Spring Boot Actuator,针对 Spring Boot Actuator 提供的 endpoint,采取以下几种措施,可以尽可能降低被安全攻击的风险
- 最小粒度暴露 endpoint。只开启并暴露真正用到的 endpoint,而不是配置:management.endpoints.web.exposure.include=*。
- 为 endpoint 配置独立的访问端口,从而和 web 服务的端口分离开,避免暴露 web 服务时,误将 actuator 的 endpoint 也暴露出去。例:management.port=8099。
- 引入 spring-boot-starter-security 依赖,为 actuator 的 endpoint 配置访问控制。
- 慎重评估是否需要引入 spring-boot-stater-actuator。以我个人的经验,我至今还没有遇到什么需求是一定需要引入spring-boot-stater-actuator 才能解决,如果你并不了解上文所述的安全风险,我建议你先去除掉该依赖。
信息安全已经成为各大公司不得不考虑的问题,所以精准的权限控制也是必不可少的,希望本文对大家在使用SpringCloud相关组件安全控制上有启发作用。
如果觉得俺写的还可以,记得点赞,一键三连也不介意。
☞☞每周一篇,赛过神仙,看完点赞,养成习惯☜☜
小心,别被eureka坑了的更多相关文章
- 最近C#项目中不小心踩的低级坑
都是很基础的错误问题,大部分都是因为不查一下资料就直接根据其它类似语言的经验写代码导致的 1. 一个企业微信上的正常的界面突然不能滚动了 本以为是浏览器代码计算问题,结果发现是JS出错导致. 2. R ...
- 记录一个微信网页授权中不小心踩到的坑(Curl请求返回false)
原文章地址在这里 这个问题是file_get_contents不能获取https的内容引起的.这样的情况下,我们一般会采用curl拓展来模拟请求. 代码demo(当然这是错误的示范): functio ...
- 小心!FOMO3D的坑
null 01 前方高能 近日,区块链机构安比(SECBIT)实验室审计后确认,FOMO3D游戏的智能合约存在随机数漏洞可被利用,FOMO3D合约及所有抄袭源码的山寨合约均存在该安全漏洞. 原本设计上 ...
- python中的这些坑,早看早避免。
python中的这些坑,早看早避免. 说一说python中遇到的坑,躲坑看这一篇就够了 传递参数时候不要使用列表 def foo(num,age=[]): age.append(num) print( ...
- alibaba之Nacos
本文为转载文章 原文链接:https://windmt.com/2018/11/09/intro-to-spring-cloud-alibaba-nacos/ 上个月最后一天的凌晨,Spring Cl ...
- [转] 传统 Ajax 已死,Fetch 永生
原谅我做一次标题党,Ajax 不会死,传统 Ajax 指的是 XMLHttpRequest(XHR),未来现在已被 Fetch 替代. 最近把阿里一个千万级 PV 的数据产品全部由 jQuery 的 ...
- 关于mybatis用mysql时,插入返回自增主键的问题
公司决定新项目用mybatis,虽然这个以前学过但是一直没用过都忘得差不多了,而且项目比较紧,也没时间去系统点的学一学,只好很粗略的百度达到能用的程度就行了. 其中涉及到插入实体要求返回主键id的问题 ...
- 面试前的准备---C#知识点回顾----03
经过一天的奔波,喜忧参半,不细表 再回看下标题,C#知识点回顾 再看下内容,数据库3NF 原谅我这个标题党 今天继续回忆 1.HTTP中Post和Get区别 这忒简单了吧,大家是不是感觉到兴奋了,长舒 ...
- 传统 Ajax 已死,Fetch 永生
原谅我做一次标题党,Ajax 不会死,传统 Ajax 指的是 XMLHttpRequest(XHR),未来现在已被 Fetch 替代. 最近把阿里一个千万级 PV 的数据产品全部由 jQuery 的 ...
随机推荐
- Nice!JavaScript基础语法知识都在这儿了
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star 转载请注明出处! 链接:https://blog.csdn ...
- js 实现红绿灯变换
class LightFn{ async run(){ while(true){ console.log('this is green 3000'); await this.sleep(3000); ...
- mybatis 一对多和多对一 简单案例笔记
以案例说明(以下案例代码都敲过验证过) 多对一(多个学生对一个老师 即学生集合中都存一个老师对象) Mybatis多对一实现方式1: //定义Student 和 Teacher 实体 @Data p ...
- css中a元素放长英文字母或者数字自动换行的解决
在做链接分享页面的时候遇到a元素中的下载链接长英文溢出不换行的问题 在给他以及他父元素设置宽度依然没有解决这个问题 最后解决办法给元素加上word-wrap:break-word 解释:使用break ...
- IntelliJ Idea tomcat 控制台输出乱码
reference: https://blog.csdn.net/dandandeshangni/article/details/485442211. 在运行/调试 配置对话框的Startup/Con ...
- TcaplusDB服务体系揭秘
导言 TcaplusDB是腾讯出品的分布式NoSQL数据库,存储和调度的代码完全自研.具备缓存+落地融合架构.PB级存储.毫秒级时延.无损水平扩展和复杂数据结构等特性.同时具备丰富的生态.便捷的迁移. ...
- 手把手教你手写一个最简单的 Spring Boot Starter
欢迎关注微信公众号:「Java之言」技术文章持续更新,请持续关注...... 第一时间学习最新技术文章 领取最新技术学习资料视频 最新互联网资讯和面试经验 何为 Starter ? 想必大家都使用过 ...
- 后端程序员之路 53、A Tour of Go-3
#method - Methods - Go does not have classes. However, you can define methods on types. ...
- SSM整合再回顾
一.spring 前言:提起spring就不得不说到它的IOC和AOP的概念.IOC就是一个对象容器,程序员可以将对象的创建交给spring的IOC容器来创建,不再使用传统的new对象方式,从而极大程 ...
- 【转载】UML类图中箭头和线条的含义和用法
文章转载自 http://blog.csdn.net/hewei0241/article/details/7674450 https://blog.csdn.net/iamherego/article ...