From 99db7a610157663249e8a8494ed304a2009f1e71 Mon Sep 17 00:00:00 2001 From: John Niang Date: Fri, 11 Oct 2024 10:45:05 +0800 Subject: [PATCH] Support redirecting to URI with fragment (#6817) #### What type of PR is this? /kind bug /area core /milestone 2.20.x #### What this PR does / why we need it: This PR supports redirecting to URI with fragment. e.g.: (redirect_uri is `/#afragment`). #### Which issue(s) this PR fixes: Fixes #6767 #### Special notes for your reviewer: 1. Request 2. Log in 3. See the redirection #### Does this PR introduce a user-facing change? ```release-note None ``` --- .../app/security/HaloServerRequestCache.java | 8 ++++++-- .../security/HaloServerRequestCacheTest.java | 17 +++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/application/src/main/java/run/halo/app/security/HaloServerRequestCache.java b/application/src/main/java/run/halo/app/security/HaloServerRequestCache.java index 0909d4020..02f146050 100644 --- a/application/src/main/java/run/halo/app/security/HaloServerRequestCache.java +++ b/application/src/main/java/run/halo/app/security/HaloServerRequestCache.java @@ -44,6 +44,7 @@ public class HaloServerRequestCache extends WebSessionServerRequestCache { public Mono saveRequest(ServerWebExchange exchange) { var redirectUriQuery = exchange.getRequest().getQueryParams().getFirst(REDIRECT_URI_QUERY); if (StringUtils.isNotBlank(redirectUriQuery)) { + // the query value is decoded, so we don't need to decode it again var redirectUri = URI.create(redirectUriQuery); return saveRedirectUri(exchange, redirectUri); } @@ -64,8 +65,11 @@ public class HaloServerRequestCache extends WebSessionServerRequestCache { var requestPath = exchange.getRequest().getPath(); var redirectPath = RequestPath.parse(redirectUri, requestPath.contextPath().value()); var query = redirectUri.getRawQuery(); - var finalRedirect = - redirectPath.pathWithinApplication() + (query == null ? "" : "?" + query); + var fragment = redirectUri.getRawFragment(); + var finalRedirect = redirectPath.pathWithinApplication() + + (query == null ? "" : "?" + query) + + (fragment == null ? "" : "#" + fragment); + return exchange.getSession() .map(WebSession::getAttributes) .doOnNext(attributes -> attributes.put(this.sessionAttrName, finalRedirect)) diff --git a/application/src/test/java/run/halo/app/security/HaloServerRequestCacheTest.java b/application/src/test/java/run/halo/app/security/HaloServerRequestCacheTest.java index 02e130c7e..aa5c09bf9 100644 --- a/application/src/test/java/run/halo/app/security/HaloServerRequestCacheTest.java +++ b/application/src/test/java/run/halo/app/security/HaloServerRequestCacheTest.java @@ -33,23 +33,28 @@ class HaloServerRequestCacheTest { @Test void shouldSaveIfPageCacheable() { var mockExchange = MockServerWebExchange.from( - MockServerHttpRequest.get("/archives").accept(MediaType.TEXT_HTML) + MockServerHttpRequest.get("/archives") + .queryParam("q", "v") + .accept(MediaType.TEXT_HTML) ); requestCache.saveRequest(mockExchange) .then(requestCache.getRedirectUri(mockExchange)) .as(StepVerifier::create) - .expectNext(URI.create("/archives")) + .expectNext(URI.create("/archives?q=v")) .verifyComplete(); } @Test - void shouldSaveIfQueryPresent() { - var mockExchange = - MockServerWebExchange.from(MockServerHttpRequest.get("/login?redirect_uri=/halo?q=v")); + void shouldSaveIfRedirectUriPresent() { + var mockExchange = MockServerWebExchange.from( + MockServerHttpRequest.get("/login") + .queryParam("redirect_uri", "/halo?q=v#fragment") + ); requestCache.saveRequest(mockExchange) .then(requestCache.getRedirectUri(mockExchange)) .as(StepVerifier::create) - .expectNext(URI.create("/halo?q=v")); + .expectNext(URI.create("/halo?q=v#fragment")) + .verifyComplete(); } @Test