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,采取以下几种措施,可以尽可能降低被安全攻击的风险

  1. 最小粒度暴露 endpoint。只开启并暴露真正用到的 endpoint,而不是配置:management.endpoints.web.exposure.include=*。
  2. 为 endpoint 配置独立的访问端口,从而和 web 服务的端口分离开,避免暴露 web 服务时,误将 actuator 的 endpoint 也暴露出去。例:management.port=8099。
  3. 引入 spring-boot-starter-security 依赖,为 actuator 的 endpoint 配置访问控制。
  4. 慎重评估是否需要引入 spring-boot-stater-actuator。以我个人的经验,我至今还没有遇到什么需求是一定需要引入spring-boot-stater-actuator 才能解决,如果你并不了解上文所述的安全风险,我建议你先去除掉该依赖。

信息安全已经成为各大公司不得不考虑的问题,所以精准的权限控制也是必不可少的,希望本文对大家在使用SpringCloud相关组件安全控制上有启发作用。

如果觉得俺写的还可以,记得点赞,一键三连也不介意。

☞☞每周一篇,赛过神仙,看完点赞,养成习惯☜☜

小心,别被eureka坑了的更多相关文章

  1. 最近C#项目中不小心踩的低级坑

    都是很基础的错误问题,大部分都是因为不查一下资料就直接根据其它类似语言的经验写代码导致的 1. 一个企业微信上的正常的界面突然不能滚动了 本以为是浏览器代码计算问题,结果发现是JS出错导致. 2. R ...

  2. 记录一个微信网页授权中不小心踩到的坑(Curl请求返回false)

    原文章地址在这里 这个问题是file_get_contents不能获取https的内容引起的.这样的情况下,我们一般会采用curl拓展来模拟请求. 代码demo(当然这是错误的示范): functio ...

  3. 小心!FOMO3D的坑

    null 01 前方高能 近日,区块链机构安比(SECBIT)实验室审计后确认,FOMO3D游戏的智能合约存在随机数漏洞可被利用,FOMO3D合约及所有抄袭源码的山寨合约均存在该安全漏洞. 原本设计上 ...

  4. python中的这些坑,早看早避免。

    python中的这些坑,早看早避免. 说一说python中遇到的坑,躲坑看这一篇就够了 传递参数时候不要使用列表 def foo(num,age=[]): age.append(num) print( ...

  5. alibaba之Nacos

    本文为转载文章 原文链接:https://windmt.com/2018/11/09/intro-to-spring-cloud-alibaba-nacos/ 上个月最后一天的凌晨,Spring Cl ...

  6. [转] 传统 Ajax 已死,Fetch 永生

    原谅我做一次标题党,Ajax 不会死,传统 Ajax 指的是 XMLHttpRequest(XHR),未来现在已被 Fetch 替代. 最近把阿里一个千万级 PV 的数据产品全部由 jQuery 的  ...

  7. 关于mybatis用mysql时,插入返回自增主键的问题

    公司决定新项目用mybatis,虽然这个以前学过但是一直没用过都忘得差不多了,而且项目比较紧,也没时间去系统点的学一学,只好很粗略的百度达到能用的程度就行了. 其中涉及到插入实体要求返回主键id的问题 ...

  8. 面试前的准备---C#知识点回顾----03

    经过一天的奔波,喜忧参半,不细表 再回看下标题,C#知识点回顾 再看下内容,数据库3NF 原谅我这个标题党 今天继续回忆 1.HTTP中Post和Get区别 这忒简单了吧,大家是不是感觉到兴奋了,长舒 ...

  9. 传统 Ajax 已死,Fetch 永生

    原谅我做一次标题党,Ajax 不会死,传统 Ajax 指的是 XMLHttpRequest(XHR),未来现在已被 Fetch 替代. 最近把阿里一个千万级 PV 的数据产品全部由 jQuery 的  ...

随机推荐

  1. true && number !== boolean

    true && number !== boolean bug let result = ``; // section, name ? create text, compute cent ...

  2. SVG 场馆图

    SVG 场馆图 https://www.infoq.cn/article/1BVg9VDSmqyHv3W3TeNH https://mp.weixin.qq.com/s/aNPAfJIHL14NFtL ...

  3. nodejs 在windows10中设置动态(视频)壁纸

    github 项目地址 node版本 λ node -v v12.16.2 main.js const ffi = require("@saleae/ffi"); const ch ...

  4. Renice INC:法国葡萄酒为什么独占世界鳌头?

    提起葡萄酒,许多人首先想到的就是法国.法国有着悠久的酿酒历史和精湛工艺,"82年的拉菲"几乎成了大众认识葡萄酒的代名词.市面上的进口葡萄酒琳琅满目,原产国众多,意大利.西班牙.美国 ...

  5. NGK DeFi Baccarat怎么玩能赚钱?

    市面上大多数DeFi项目都是基于以太坊来开发的,除了吞吐量低.存储量小以及交易速度慢等问题以外,高额的Gas手续费将不少终端用户拒之门外. 基于此NGK.IO推出了低门槛的DeFi项目-- Bacca ...

  6. 无法将“node.exe”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

    有些天没有启动前端项目,发现npm run dev,启动不了,经过一番查找发现问题所在 然后我查看了一下报错位置,发现并没有改动过什么 解决方法: 方法一: 检查一下npm目录: 这里发现少了node ...

  7. Java Socket编程基础及深入讲解

    原文链接:https://www.cnblogs.com/yiwangzhibujian/p/7107785.html 原文写的特别好,非常详细,但是禁止转载,那我就不再复制粘贴了! socket实现 ...

  8. 鸿蒙开源第三方组件 ——B站开源弹幕库引擎的迁移(上)

    鸿蒙入门指南,小白速来!0基础学习路线分享,高效学习方法,重点答疑解惑--->[课程入口] 目录: 一.弹幕库的基础知识 二.弹幕库的使用方法 三.sample解析 四.作者系列文章合集 前言 ...

  9. Bitter.NotifyOpenPaltform : HTTP 异步消息接收调度中心&mdash;开源贡献 之 一:简介

    现在互联网的系统越来越趋向于复杂,从单体系统到现在的微服务体系演变.公司与公司的分工也越来越明确. 大数据公司提供了大数据服务 人脸识别公司提供了人脸识别服务 OCR 公司提供了专业的OCR 服务 车 ...

  10. 关于电脑硬盘的二三事(SATA接口)

    @ 目录 前言 接口分类 SATA3接口 机械硬盘 机械硬盘的特点和主要参数 西部数据机械盘分类 绿·蓝·黑盘 红盘 紫盘 金盘 希捷机械盘分类 酷狼 酷鱼 酷鹰 银河 SATA3接口的固态硬盘 固态 ...