• Java配置47-Spring Eureka 未授权访问漏洞修复


    1. 背景

    项目组使用的 Spring Boot 比较老,是 1.5.4.RELEASE 。最近被检测出 Spring Eureka 未授权访问漏洞。

    现状是浏览器直接访问 Eureka Server 可以直接进去,看到已经注册的服务信息。

    在这里插入图片描述

    2. 方法

    2.1 Eureka Server 添加安全组件

    Eureka Server 添加 pom 依赖:

            
                org.springframework.boot
                spring-boot-starter-security
            
    
    • 1
    • 2
    • 3
    • 4

    2.2 Eureka Server 添加参数

    spring.application.name:demo-eureka
    server.port: 8088
    eureka.instance.hostname=localhost
    #禁用将自己作为客户端注册,禁用客户端注册行为
    eureka.client.register-with-eureka=false
    eureka.client.fetch-registry=false
    #eureka地址
    eureka.client.service-url.defaultZone=http://${spring.security.user.name}:${spring.security.user.password}@${eureka.instance.hostname}:${server.port}/eureka
    #eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka
    #关闭自我保护 --本地开发环境可以关闭,生产环境
    eureka.server.enable-self-preservation = false
    #清理节点时间
    eureka.server.eviction-interval-timer-in-ms = 60000
    spring.security.basic.enabled=true
    spring.security.user.name=demo
    spring.security.user.password=123abcd
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.3 重启 Eureka Server

    重启 Eureka Server ,然后刷新访问页面,显示登录框:

    在这里插入图片描述

    输入配置的用户名和密码。

    spring.security.user.name=demo
    spring.security.user.password=123abcd
    
    • 1
    • 2

    然后就报错了:Reason: Bad credentials。

    在这里插入图片描述

    奇怪,明明是按照配置文件里面输入的,怎么还会报用户名或密码错误呢。

    查了一些资料,说跟 security 加密方法有关,整了半天搞不定。

    2.4 Eureka Server 升级版本

    实在没招了,只能怀疑用的框架版本太低,去重新整一个,eureka 就用了个服务发现,问题不大。

    访问:https://start.spring.io/

    在这里插入图片描述

    把项目下载到本地,依赖已经加好了:

    	
    		
    			org.springframework.boot
    			spring-boot-starter-security
    		
    		
    			org.springframework.cloud
    			spring-cloud-starter-netflix-eureka-server
    		
    
    		
    			org.springframework.boot
    			spring-boot-starter-test
    			test
    		
    		
    			org.springframework.security
    			spring-security-test
    			test
    		
    	
    	
    		
    			
    				org.springframework.cloud
    				spring-cloud-dependencies
    				${spring-cloud.version}
    				pom
    				import
    			
    		
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在启动类上加上注解:

    package com.demo.cloudeurekaserver;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @EnableEurekaServer
    @SpringBootApplication
    public class CloudEurekaServerApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(CloudEurekaServerApplication.class, args);
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    再把 2.2 的参数加到 properties 文件中(最好换个 server.port),然后 run 启动类,访问 eureka ,输入用户名和密码,进去了:

    在这里插入图片描述

    2.5 Eureka Client 配置

    eureka client 参数:

    eureka.client.enabled=true
    eureka.client.eureka-server-port=8089
    eureka.client.service-url.defaultZone=http://demo:123abcd@localhost:8089/eureka/
    
    • 1
    • 2
    • 3

    启动 eureka client,报错:

    javax.ws.rs.WebApplicationException: null
    	at com.netflix.discovery.provider.DiscoveryJerseyProvider.readFrom(DiscoveryJerseyProvider.java:110)
    	at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:634)
    	at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:586)
    	at com.netflix.discovery.shared.transport.jersey.AbstractJerseyEurekaHttpClient.sendHeartBeat(AbstractJerseyEurekaHttpClient.java:105)
    	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$3.execute(EurekaHttpClientDecorator.java:92)
    	at com.netflix.discovery.shared.transport.decorator.MetricsCollectingEurekaHttpClient.execute(MetricsCollectingEurekaHttpClient.java:73)
    	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89)
    	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$3.execute(EurekaHttpClientDecorator.java:92)
    	at com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient.executeOnNewServer(RedirectingEurekaHttpClient.java:118)
    	at com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient.execute(RedirectingEurekaHttpClient.java:79)
    	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89)
    	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$3.execute(EurekaHttpClientDecorator.java:92)
    	at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:119)
    	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89)
    	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$3.execute(EurekaHttpClientDecorator.java:92)
    	at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77)
    	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89)
    	at com.netflix.discovery.DiscoveryClient.renew(DiscoveryClient.java:824)
    	at com.netflix.discovery.DiscoveryClient$HeartbeatThread.run(DiscoveryClient.java:1388)
    	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    
    2023-11-03 14:41:26.339  WARN [test-app-service,,,] 16240 --- [tbeatExecutor-0] c.n.d.s.t.d.RetryableEurekaHttpClient    : Request execution failed with message: null
    2023-11-03 14:41:26.339 ERROR [test-app-service,,,] 16240 --- [tbeatExecutor-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_TEST-APP-SERVICE/10.136.44.122:test-app-service:60000 - was unable to send heartbeat!
    
    com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
    	at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:111)
    	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89)
    	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$3.execute(EurekaHttpClientDecorator.java:92)
    	at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77)
    	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89)
    	at com.netflix.discovery.DiscoveryClient.renew(DiscoveryClient.java:824)
    	at com.netflix.discovery.DiscoveryClient$HeartbeatThread.run(DiscoveryClient.java:1388)
    	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at java.lang.Thread.run(Thread.java:748)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    刷新 eureka 页面,也没有服务信息,服务注册失败了。

    这是因为从 Spring Boot 2.0 开始,默认情况下会启用CSRF保护,以防止CSRF攻击应用程序,导致服务注册失败。

    2.6 Eureka Server 添加代码

    修改 Eureka Server :

    package com.demo.cloudeurekaserver;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    @EnableEurekaServer
    @SpringBootApplication
    public class CloudEurekaServerApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(CloudEurekaServerApplication.class, args);
    	}
    
    	/**
    	 * springboot 从 2.0 开始,默认情况下会启用CSRF保护
    	 * 需要关闭
    	 */
    	@EnableWebSecurity
    	static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    		@Override
    		protected void configure(HttpSecurity http) throws Exception {
    			//方法1:关闭csrf
    //			http.csrf().disable();
    			//方法2:忽略/eureka/** 所有请求
    			http.csrf().ignoringAntMatchers("/eureka/**");
    			super.configure(http);
    		}
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    重启 Eureka Server 和 Eureka Client ,这次没有报错,刷新页面,重新登录后,看到注册的服务信息:

    在这里插入图片描述

    2.7 其他问题

    在 Spring Security 5.7.0-M2 中,WebSecurityConfigurerAdapter 被弃用了,Spring 鼓励用户转向基于组件的安全配置。这意味着,现在应该使用基于组件的安全配置来配置 HttpSecurity,而不是继承 WebSecurityConfigurerAdapter。这种方式更加灵活,可以更好地支持 Spring Boot 2.x 和 Spring 5.x。

    在这里插入图片描述

    我试了几个方法,没有替换掉,靠你了,耿小姐。

    先这样吧。
    在这里插入图片描述
    (图网,侵删)

  • 相关阅读:
    〖全域运营实战白宝书 - 高转化文案速成篇④〗- 如何撰写摘要型文案?
    calibre和cpolar搭建一个私有的网络书库
    Matlab GUI编程技巧(六):从一个GUI界面跳转到另一个GUI界面以及GUI窗口间数据传递
    惊艳!拓世法宝AI智能数字人一体机解锁数字文博的全民体验
    C语言简述
    leetcode11 盛水最多的容器
    C#中async/await的线程ID变化情况
    pdf怎么编辑文字?了解一下这几种编辑方法
    java io流
    著者 许少辉 著. 乡村振兴战略下传统村落文化旅游设计 [专著] / 许少辉著中文文献总库 - 北京交通大学馆藏辉少许
  • 原文地址:https://blog.csdn.net/JustDI0209/article/details/134206920