文章目录
1. 背景
项目组使用的 spring boot 比较老,是 1.5.4.release 。最近被检测出 spring eureka 未授权访问漏洞。
现状是浏览器直接访问 eureka server 可以直接进去,看到已经注册的服务信息。
2. 方法
2.1 eureka server 添加安全组件
eureka server 添加 pom 依赖:
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-security</artifactid>
</dependency>
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
2.3 重启 eureka server
重启 eureka server ,然后刷新访问页面,显示登录框:
输入配置的用户名和密码。
spring.security.user.name=demo
spring.security.user.password=123abcd
然后就报错了:reason: bad credentials。
奇怪,明明是按照配置文件里面输入的,怎么还会报用户名或密码错误呢。
查了一些资料,说跟 security 加密方法有关,整了半天搞不定。
2.4 eureka server 升级版本
实在没招了,只能怀疑用的框架版本太低,去重新整一个,eureka 就用了个服务发现,问题不大。
访问:https://start.spring.io/
把项目下载到本地,依赖已经加好了:
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-security</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.cloud</groupid>
<artifactid>spring-cloud-starter-netflix-eureka-server</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-test</artifactid>
<scope>test</scope>
</dependency>
<dependency>
<groupid>org.springframework.security</groupid>
<artifactid>spring-security-test</artifactid>
<scope>test</scope>
</dependency>
</dependencies>
<dependencymanagement>
<dependencies>
<dependency>
<groupid>org.springframework.cloud</groupid>
<artifactid>spring-cloud-dependencies</artifactid>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
在启动类上加上注解:
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);
}
}
再把 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/
启动 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)
刷新 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);
}
}
}
重启 eureka server 和 eureka client ,这次没有报错,刷新页面,重新登录后,看到注册的服务信息:
2.7 其他问题
在 spring security 5.7.0-m2 中,websecurityconfigureradapter 被弃用了,spring 鼓励用户转向基于组件的安全配置。这意味着,现在应该使用基于组件的安全配置来配置 httpsecurity,而不是继承 websecurityconfigureradapter。这种方式更加灵活,可以更好地支持 spring boot 2.x 和 spring 5.x。
我试了几个方法,没有替换掉,靠你了,耿小姐。
先这样吧。
(图网,侵删)
发表评论