Skip to content

Commit bea308e

Browse files
committed
Merge remote-tracking branch 'origin/master' into experimental/spring-boot-3-playground
2 parents b5b2100 + 702c951 commit bea308e

File tree

13 files changed

+123
-13
lines changed

13 files changed

+123
-13
lines changed

.github/workflows/build-feature.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
java-version: '17'
2727

2828
- name: Cache local Maven repository
29-
uses: actions/[email protected].10
29+
uses: actions/[email protected].11
3030
env:
3131
cache-name: cache-mvn
3232
with:

.github/workflows/build-main.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
java-version: '17'
2626

2727
- name: Cache local Maven repository
28-
uses: actions/[email protected].10
28+
uses: actions/[email protected].11
2929
env:
3030
cache-name: cache-mvn
3131
with:
@@ -71,7 +71,7 @@ jobs:
7171
java-version: '8'
7272

7373
- name: Cache local Maven repository
74-
uses: actions/[email protected].10
74+
uses: actions/[email protected].11
7575
env:
7676
cache-name: cache-mvn
7777
with:
@@ -107,7 +107,7 @@ jobs:
107107
run: echo ${{ steps.project.outputs.version }}
108108

109109
- name: Deploy Asciidoc docs output to GitHub Pages
110-
uses: JamesIves/[email protected].0
110+
uses: JamesIves/[email protected].1
111111
with:
112112
branch: gh-pages # The branch the action should deploy to.
113113
folder: spring-boot-admin-docs/target/generated-docs # The folder the action should deploy.

.github/workflows/build-pullrequest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
java-version: '17'
2222

2323
- name: Cache local Maven repository
24-
uses: actions/[email protected].10
24+
uses: actions/[email protected].11
2525
env:
2626
cache-name: cache-mvn
2727
with:

.github/workflows/release-to-maven-central.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
gpg-passphrase: MAVEN_GPG_PASSPHRASE
2929

3030
- name: Cache local Maven repository
31-
uses: actions/[email protected].10
31+
uses: actions/[email protected].11
3232
env:
3333
cache-name: cache-mvn
3434
with:
@@ -62,7 +62,7 @@ jobs:
6262
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
6363

6464
- name: Deploy Asciidoc docs output to GitHub Pages
65-
uses: JamesIves/[email protected].0
65+
uses: JamesIves/[email protected].1
6666
with:
6767
branch: gh-pages # The branch the action should deploy to.
6868
folder: spring-boot-admin-docs/target/generated-docs # The folder the action should deploy.

spring-boot-admin-client/src/main/java/de/codecentric/boot/admin/client/registration/ReactiveApplicationFactory.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,19 @@
2121
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
2222
import org.springframework.boot.autoconfigure.web.ServerProperties;
2323
import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties;
24+
import org.springframework.boot.web.server.Ssl;
25+
import org.springframework.util.StringUtils;
2426
import org.springframework.web.util.UriComponentsBuilder;
2527

2628
import de.codecentric.boot.admin.client.config.InstanceProperties;
2729
import de.codecentric.boot.admin.client.registration.metadata.MetadataContributor;
2830

2931
public class ReactiveApplicationFactory extends DefaultApplicationFactory {
3032

33+
private ManagementServerProperties management;
34+
35+
private final ServerProperties server;
36+
3137
private WebFluxProperties webflux;
3238

3339
private InstanceProperties instance;
@@ -36,6 +42,8 @@ public ReactiveApplicationFactory(InstanceProperties instance, ManagementServerP
3642
ServerProperties server, PathMappedEndpoints pathMappedEndpoints, WebEndpointProperties webEndpoint,
3743
MetadataContributor metadataContributor, WebFluxProperties webFluxProperties) {
3844
super(instance, management, server, pathMappedEndpoints, webEndpoint, metadataContributor);
45+
this.management = management;
46+
this.server = server;
3947
this.webflux = webFluxProperties;
4048
this.instance = instance;
4149
}
@@ -50,6 +58,27 @@ protected String getServiceUrl() {
5058
.toUriString();
5159
}
5260

61+
@Override
62+
protected String getManagementBaseUrl() {
63+
String baseUrl = this.instance.getManagementBaseUrl();
64+
65+
if (StringUtils.hasText(baseUrl)) {
66+
return baseUrl;
67+
}
68+
69+
if (isManagementPortEqual()) {
70+
return this.getServiceUrl();
71+
}
72+
73+
Ssl ssl = (this.management.getSsl() != null) ? this.management.getSsl() : this.server.getSsl();
74+
return UriComponentsBuilder.newInstance().scheme(getScheme(ssl)).host(getManagementHost())
75+
.port(getLocalManagementPort()).path(getManagementContextPath()).toUriString();
76+
}
77+
78+
protected String getManagementContextPath() {
79+
return management.getBasePath();
80+
}
81+
5382
protected String getWebfluxBasePath() {
5483
return webflux.getBasePath();
5584
}

spring-boot-admin-client/src/test/java/de/codecentric/boot/admin/client/registration/ReactiveApplicationFactoryTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,19 @@ public void test_noBasePath() {
109109
assertThat(app.getServiceUrl()).isEqualTo("http://" + getHostname() + ":80/");
110110
}
111111

112+
@Test
113+
public void test_mgmtBasePath_mgmtPortPath() {
114+
webflux.setBasePath("/app");
115+
management.setBasePath("/mgnt");
116+
when(pathMappedEndpoints.getPath(EndpointId.of("health"))).thenReturn("/actuator/health");
117+
publishApplicationReadyEvent(factory, 8080, 8081);
118+
119+
Application app = factory.createApplication();
120+
assertThat(app.getManagementUrl()).isEqualTo("http://" + getHostname() + ":8081/mgnt/actuator");
121+
assertThat(app.getHealthUrl()).isEqualTo("http://" + getHostname() + ":8081/mgnt/actuator/health");
122+
assertThat(app.getServiceUrl()).isEqualTo("http://" + getHostname() + ":8080/app");
123+
}
124+
112125
private String getHostname() {
113126
try {
114127
return InetAddress.getLocalHost().getCanonicalHostName();
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2014-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package de.codecentric.boot.admin;
18+
19+
import java.io.IOException;
20+
21+
import jakarta.servlet.FilterChain;
22+
import jakarta.servlet.ServletException;
23+
import jakarta.servlet.http.Cookie;
24+
import jakarta.servlet.http.HttpServletRequest;
25+
import jakarta.servlet.http.HttpServletResponse;
26+
27+
import org.springframework.security.web.csrf.CsrfToken;
28+
import org.springframework.web.filter.OncePerRequestFilter;
29+
import org.springframework.web.util.WebUtils;
30+
31+
public class CustomCsrfFilter extends OncePerRequestFilter {
32+
33+
public static final String CSRF_COOKIE_NAME = "XSRF-TOKEN";
34+
35+
@Override
36+
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
37+
throws ServletException, IOException {
38+
39+
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
40+
41+
if (csrf != null) {
42+
43+
Cookie cookie = WebUtils.getCookie(request, CSRF_COOKIE_NAME);
44+
String token = csrf.getToken();
45+
46+
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
47+
cookie = new Cookie(CSRF_COOKIE_NAME, token);
48+
cookie.setPath("/");
49+
response.addCookie(cookie);
50+
}
51+
}
52+
53+
filterChain.doFilter(request, response);
54+
}
55+
56+
}

spring-boot-admin-samples/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/SecuritySecureConfig.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
3434
import org.springframework.security.web.SecurityFilterChain;
3535
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
36+
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
3637
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
38+
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
3739
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
3840

3941
import de.codecentric.boot.admin.server.config.AdminServerProperties;
@@ -72,14 +74,18 @@ protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
7274
.formLogin((formLogin) -> formLogin.loginPage(this.adminServer.path("/login"))
7375
.successHandler(successHandler)) // <3>
7476
.logout((logout) -> logout.logoutUrl(this.adminServer.path("/logout")))
75-
.httpBasic(Customizer.withDefaults()) // <4>
76-
.csrf((csrf) -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // <5>
77-
.ignoringRequestMatchers(
77+
.httpBasic(Customizer.withDefaults()); // <4>
78+
79+
http.addFilterAfter(new CustomCsrfFilter(), BasicAuthenticationFilter.class) // <5>
80+
.csrf((csrf) -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
81+
.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()).ignoringRequestMatchers(
7882
new AntPathRequestMatcher(this.adminServer.path("/instances"), POST.toString()), // <6>
7983
new AntPathRequestMatcher(this.adminServer.path("/instances/*"), DELETE.toString()), // <6>
8084
new AntPathRequestMatcher(this.adminServer.path("/actuator/**")) // <7>
81-
))
82-
.rememberMe((rememberMe) -> rememberMe.key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600));
85+
));
86+
87+
http.rememberMe((rememberMe) -> rememberMe.key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600));
88+
8389
return http.build();
8490

8591
}

spring-boot-admin-samples/spring-boot-admin-sample-servlet/src/main/resources/application.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ management:
1919
exposure:
2020
include: "*"
2121
endpoint:
22+
jolokia:
23+
enabled: true
2224
refresh:
2325
enabled: true
2426
restart:

spring-boot-admin-server-ui/src/main/frontend/test-utils.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const render = (testComponent, options) => {
1616
messages: {
1717
en: terms,
1818
},
19+
legacy: false,
1920
silentFallbackWarn: true,
2021
silentTranslationWarn: true,
2122
}),

0 commit comments

Comments
 (0)