Skip to content

Commit 5c4dd51

Browse files
Fix CAS Client Java lib not working with Jakarta EE 9
Copy the code from the library and change it to support the Jakarta classes Issue spring-projectsgh-10360
1 parent db60df2 commit 5c4dd51

File tree

4 files changed

+179
-4
lines changed

4 files changed

+179
-4
lines changed

cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import jakarta.servlet.http.HttpServletRequest;
2222
import jakarta.servlet.http.HttpServletResponse;
2323

24-
import org.jasig.cas.client.util.CommonUtils;
25-
2624
import org.springframework.beans.factory.InitializingBean;
2725
import org.springframework.security.cas.ServiceProperties;
2826
import org.springframework.security.core.AuthenticationException;
@@ -96,7 +94,7 @@ protected String createServiceUrl(HttpServletRequest request, HttpServletRespons
9694
*/
9795
protected String createRedirectUrl(String serviceUrl) {
9896
return CommonUtils.constructRedirectUrl(this.loginUrl, this.serviceProperties.getServiceParameter(), serviceUrl,
99-
this.serviceProperties.isSendRenew(), false);
97+
this.serviceProperties.isSendRenew(), false, null);
10098
}
10199

102100
/**

cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import jakarta.servlet.http.HttpServletResponse;
2525

2626
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
27-
import org.jasig.cas.client.util.CommonUtils;
2827
import org.jasig.cas.client.validation.TicketValidator;
2928

3029
import org.springframework.core.log.LogMessage;
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* Licensed to Apereo under one or more contributor license
3+
* agreements. See the NOTICE file distributed with this work
4+
* for additional information regarding copyright ownership.
5+
* Apereo licenses this file to you under the Apache License,
6+
* Version 2.0 (the "License"); you may not use this file
7+
* except in compliance with the License. You may obtain a
8+
* copy of the License at the following location:
9+
*
10+
* https://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.springframework.security.cas.web;
21+
22+
import java.io.IOException;
23+
import java.net.URLEncoder;
24+
import java.nio.charset.StandardCharsets;
25+
import java.util.Arrays;
26+
import java.util.HashSet;
27+
import java.util.List;
28+
import java.util.Set;
29+
30+
import jakarta.servlet.http.HttpServletRequest;
31+
import jakarta.servlet.http.HttpServletResponse;
32+
33+
import org.jasig.cas.client.Protocol;
34+
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
35+
import org.jasig.cas.client.util.URIBuilder;
36+
37+
import org.springframework.util.StringUtils;
38+
39+
final class CommonUtils {
40+
41+
private static final String PARAM_PROXY_GRANTING_TICKET_IOU = "pgtIou";
42+
43+
/**
44+
* Constant representing the ProxyGrantingTicket Request Parameter.
45+
*/
46+
private static final String PARAM_PROXY_GRANTING_TICKET = "pgtId";
47+
48+
private static final String SERVICE_PARAMETER_NAMES;
49+
50+
private CommonUtils() {
51+
52+
}
53+
54+
static {
55+
final Set<String> serviceParameterSet = new HashSet<String>(4);
56+
for (final Protocol protocol : Protocol.values()) {
57+
serviceParameterSet.add(protocol.getServiceParameterName());
58+
}
59+
SERVICE_PARAMETER_NAMES = serviceParameterSet.toString().replaceAll("\\[|\\]", "").replaceAll("\\s", "");
60+
}
61+
62+
static String constructServiceUrl(final HttpServletRequest request, final HttpServletResponse response,
63+
final String service, final String serverNames, final String artifactParameterName, final boolean encode) {
64+
if (StringUtils.hasText(service)) {
65+
return encode ? response.encodeURL(service) : service;
66+
}
67+
68+
final String serverName = findMatchingServerName(request, serverNames);
69+
final URIBuilder originalRequestUrl = new URIBuilder(request.getRequestURL().toString(), encode);
70+
originalRequestUrl.setParameters(request.getQueryString());
71+
72+
final URIBuilder builder;
73+
if (!serverName.startsWith("https://") && !serverName.startsWith("http://")) {
74+
final String scheme = request.isSecure() ? "https://" : "http://";
75+
builder = new URIBuilder(scheme + serverName, encode);
76+
}
77+
else {
78+
builder = new URIBuilder(serverName, encode);
79+
}
80+
81+
if (builder.getPort() == -1 && !requestIsOnStandardPort(request)) {
82+
builder.setPort(request.getServerPort());
83+
}
84+
85+
builder.setEncodedPath(builder.getEncodedPath() + request.getRequestURI());
86+
87+
final List<String> serviceParameterNames = Arrays.asList(SERVICE_PARAMETER_NAMES.split(","));
88+
if (!serviceParameterNames.isEmpty() && !originalRequestUrl.getQueryParams().isEmpty()) {
89+
for (final URIBuilder.BasicNameValuePair pair : originalRequestUrl.getQueryParams()) {
90+
final String name = pair.getName();
91+
if (!name.equals(artifactParameterName) && !serviceParameterNames.contains(name)) {
92+
if (name.contains("&") || name.contains("=")) {
93+
final URIBuilder encodedParamBuilder = new URIBuilder();
94+
encodedParamBuilder.setParameters(name);
95+
for (final URIBuilder.BasicNameValuePair pair2 : encodedParamBuilder.getQueryParams()) {
96+
final String name2 = pair2.getName();
97+
if (!name2.equals(artifactParameterName) && !serviceParameterNames.contains(name2)) {
98+
builder.addParameter(name2, pair2.getValue());
99+
}
100+
}
101+
}
102+
else {
103+
builder.addParameter(name, pair.getValue());
104+
}
105+
}
106+
}
107+
}
108+
109+
final String result = builder.toString();
110+
final String returnValue = encode ? response.encodeURL(result) : result;
111+
return returnValue;
112+
}
113+
114+
static String constructRedirectUrl(final String casServerLoginUrl, final String serviceParameterName,
115+
final String serviceUrl, final boolean renew, final boolean gateway, final String method) {
116+
return casServerLoginUrl + (casServerLoginUrl.contains("?") ? "&" : "?") + serviceParameterName + "="
117+
+ urlEncode(serviceUrl) + (renew ? "&renew=true" : "") + (gateway ? "&gateway=true" : "")
118+
+ ((method != null) ? "&method=" + method : "");
119+
}
120+
121+
static String urlEncode(final String value) {
122+
return URLEncoder.encode(value, StandardCharsets.UTF_8);
123+
}
124+
125+
static void readAndRespondToProxyReceptorRequest(final HttpServletRequest request,
126+
final HttpServletResponse response, final ProxyGrantingTicketStorage proxyGrantingTicketStorage)
127+
throws IOException {
128+
final String proxyGrantingTicketIou = request.getParameter(PARAM_PROXY_GRANTING_TICKET_IOU);
129+
130+
final String proxyGrantingTicket = request.getParameter(PARAM_PROXY_GRANTING_TICKET);
131+
132+
if (org.jasig.cas.client.util.CommonUtils.isBlank(proxyGrantingTicket)
133+
|| org.jasig.cas.client.util.CommonUtils.isBlank(proxyGrantingTicketIou)) {
134+
response.getWriter().write("");
135+
return;
136+
}
137+
138+
proxyGrantingTicketStorage.save(proxyGrantingTicketIou, proxyGrantingTicket);
139+
140+
response.getWriter().write("<?xml version=\"1.0\"?>");
141+
response.getWriter().write("<casClient:proxySuccess xmlns:casClient=\"https://www.yale.edu/tp/casClient\" />");
142+
}
143+
144+
private static String findMatchingServerName(final HttpServletRequest request, final String serverName) {
145+
final String[] serverNames = serverName.split(" ");
146+
147+
if (serverNames.length == 0 || serverNames.length == 1) {
148+
return serverName;
149+
}
150+
151+
final String host = request.getHeader("Host");
152+
final String xHost = request.getHeader("X-Forwarded-Host");
153+
154+
final String comparisonHost;
155+
comparisonHost = (xHost != null) ? xHost : host;
156+
157+
if (comparisonHost == null) {
158+
return serverName;
159+
}
160+
161+
for (final String server : serverNames) {
162+
final String lowerCaseServer = server.toLowerCase();
163+
164+
if (lowerCaseServer.contains(comparisonHost)) {
165+
return server;
166+
}
167+
}
168+
169+
return serverNames[0];
170+
}
171+
172+
private static boolean requestIsOnStandardPort(final HttpServletRequest request) {
173+
final int serverPort = request.getServerPort();
174+
return serverPort == 80 || serverPort == 443;
175+
}
176+
177+
}

etc/checkstyle/checkstyle-suppressions.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
<!-- Ignore third-party code -->
1515
<suppress files="BCrypt\.java|BCryptTests\.java" checks=".*"/>
16+
<suppress files="org[\\/]springframework[\\/]security[\\/]cas[\\/]web[\\/]CommonUtils\.java" checks=".*"/>
1617
<suppress files="org[\\/]springframework[\\/]security[\\/]core[\\/]ComparableVersion\.java" checks=".*"/>
1718

1819
<!-- InterfaceIsType rules we can't fix until a major revision due to back compatibility -->

0 commit comments

Comments
 (0)