Merge pull request #231 from Unicon/urlenc-queryparams

Handle un-encoded query strings in url parameters as embedded query strings
This commit is contained in:
Misagh Moayyed 2018-03-08 15:58:35 +01:00 committed by GitHub
commit c015e226ba
2 changed files with 60 additions and 34 deletions

View File

@ -28,13 +28,13 @@ import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
/**
* A utility class borrowed from apache http-client to build uris.
*
* @author Misagh Moayyed
* @since 3.4
*/
@ -99,14 +99,15 @@ public final class URIBuilder {
/**
* Construct an instance from the provided URI.
* @param uri the uri to digest
*
* @param uri the uri to digest
*/
public URIBuilder(final URI uri) {
super();
digestURI(uri);
}
private List <BasicNameValuePair> parseQuery(final String query) {
private List<BasicNameValuePair> parseQuery(final String query) {
try {
final Charset utf8 = Charset.forName("UTF-8");
@ -115,11 +116,23 @@ public final class URIBuilder {
final String[] parametersArray = query.split("&");
for (final String parameter : parametersArray) {
final String[] parameterCombo = parameter.split("=");
if (parameterCombo.length >= 1) {
final String key = URLDecoder.decode(parameterCombo[0], utf8.name());
final String val = parameterCombo.length == 2 ? URLDecoder.decode(parameterCombo[1], utf8.name()) : "";
list.add(new BasicNameValuePair(key, val));
final int firstIndex = parameter.indexOf("=");
if (firstIndex != -1) {
final String paramName = parameter.substring(0, firstIndex);
final String decodedParamName = URLDecoder.decode(paramName, utf8.name());
final String paramVal = parameter.substring(firstIndex + 1);
final String decodedParamVal = URLDecoder.decode(paramVal, utf8.name());
list.add(new BasicNameValuePair(decodedParamName, decodedParamVal));
} else {
// Either we do not have a query parameter, or it might be encoded; take it verbaitm
final String[] parameterCombo = parameter.split("=");
if (parameterCombo.length >= 1) {
final String key = URLDecoder.decode(parameterCombo[0], utf8.name());
final String val = parameterCombo.length == 2 ? URLDecoder.decode(parameterCombo[1], utf8.name()) : "";
list.add(new BasicNameValuePair(key, val));
}
}
}
return list;
@ -327,7 +340,7 @@ public final class URIBuilder {
* will remove custom query if present.
* </p>
*/
public URIBuilder setParameters(final List <BasicNameValuePair> nvps) {
public URIBuilder setParameters(final List<BasicNameValuePair> nvps) {
this.queryParams = new ArrayList<BasicNameValuePair>();
this.queryParams.addAll(nvps);
this.encodedQuery = null;
@ -346,7 +359,6 @@ public final class URIBuilder {
}
/**
* Adds URI query parameters. The parameter name / values are expected to be unescaped
* and may contain non ASCII characters.
@ -355,7 +367,7 @@ public final class URIBuilder {
* will remove custom query if present.
* </p>
*/
public URIBuilder addParameters(final List <BasicNameValuePair> nvps) {
public URIBuilder addParameters(final List<BasicNameValuePair> nvps) {
if (this.queryParams == null || this.queryParams.isEmpty()) {
this.queryParams = new ArrayList<BasicNameValuePair>();
}
@ -380,7 +392,7 @@ public final class URIBuilder {
} else {
this.queryParams.clear();
}
for (final BasicNameValuePair nvp: nvps) {
for (final BasicNameValuePair nvp : nvps) {
this.queryParams.add(nvp);
}
this.encodedQuery = null;
@ -602,7 +614,7 @@ public final class URIBuilder {
/**
* Default Constructor taking a name and a value. The value may be null.
*
* @param name The name.
* @param name The name.
* @param value The value.
*/
public BasicNameValuePair(final String name, final String value) {
@ -647,7 +659,7 @@ public final class URIBuilder {
if (object instanceof BasicNameValuePair) {
final BasicNameValuePair that = (BasicNameValuePair) object;
return this.name.equals(that.name)
&& this.value.equals(that.value);
&& this.value.equals(that.value);
}
return false;
}

View File

@ -18,17 +18,18 @@
*/
package org.jasig.cas.client.util;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import junit.framework.TestCase;
import org.jasig.cas.client.Protocol;
import org.jasig.cas.client.PublicTestHttpServer;
import org.jasig.cas.client.ssl.HttpsURLConnectionFactory;
import org.junit.Ignore;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
/**
* Tests for the CommonUtils.
*
@ -133,7 +134,7 @@ public final class CommonUtilsTests extends TestCase {
request.setSecure(true);
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null, "www.myserver.com",
"service", "ticket", false);
"service", "ticket", false);
assertEquals(CONST_MY_URL, constructedUrl);
}
@ -147,7 +148,7 @@ public final class CommonUtilsTests extends TestCase {
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null, "www.myserver.com",
Protocol.CAS3.getServiceParameterName(), Protocol.CAS3.getArtifactParameterName() , false);
Protocol.CAS3.getServiceParameterName(), Protocol.CAS3.getArtifactParameterName(), false);
assertEquals("https://www.myserver.com/hello/hithere/?custom=custom", constructedUrl);
}
@ -161,7 +162,7 @@ public final class CommonUtilsTests extends TestCase {
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null, "https://www.myserver.com",
Protocol.CAS3.getServiceParameterName(), Protocol.CAS3.getArtifactParameterName() , false);
Protocol.CAS3.getServiceParameterName(), Protocol.CAS3.getArtifactParameterName(), false);
assertEquals("https://www.myserver.com/hello/hithere/?custom=custom", constructedUrl);
}
@ -176,7 +177,7 @@ public final class CommonUtilsTests extends TestCase {
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null, "www.myserver.com",
Protocol.SAML11.getServiceParameterName(), Protocol.SAML11.getArtifactParameterName() , false);
Protocol.SAML11.getServiceParameterName(), Protocol.SAML11.getArtifactParameterName(), false);
assertEquals("https://www.myserver.com/hello/hithere/?custom=custom", constructedUrl);
}
@ -190,7 +191,7 @@ public final class CommonUtilsTests extends TestCase {
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null, "www.myserver.com",
Protocol.SAML11.getServiceParameterName(), Protocol.SAML11.getArtifactParameterName() , false);
Protocol.SAML11.getServiceParameterName(), Protocol.SAML11.getArtifactParameterName(), false);
assertEquals("https://www.myserver.com/hello/hithere/?custom=custom", constructedUrl);
}
@ -204,13 +205,12 @@ public final class CommonUtilsTests extends TestCase {
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null, "www.myserver.com",
Protocol.SAML11.getArtifactParameterName() , true);
Protocol.SAML11.getArtifactParameterName(), true);
assertEquals("https://www.myserver.com/hello/hithere/?custom=custom", constructedUrl);
}
public void testConstructServiceUrlWithEncodedParams2Saml() {
final String CONST_MY_URL = "https://www.myserver.com/hello/hithere/";
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hello/hithere/");
request.setScheme("https");
request.setSecure(true);
@ -218,13 +218,12 @@ public final class CommonUtilsTests extends TestCase {
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null, "www.myserver.com",
Protocol.SAML11.getServiceParameterName(), Protocol.SAML11.getArtifactParameterName() , true);
Protocol.SAML11.getServiceParameterName(), Protocol.SAML11.getArtifactParameterName(), true);
assertEquals("https://www.myserver.com/hello/hithere/?custom=custom+value+here&another=good", constructedUrl);
}
public void testConstructServiceUrlWithoutEncodedParamsSamlAndNoEncoding() {
final String CONST_MY_URL = "https://www.myserver.com/hello/hithere/";
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hello/hithere/");
request.setScheme("https");
request.setSecure(true);
@ -232,7 +231,7 @@ public final class CommonUtilsTests extends TestCase {
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null, "www.myserver.com",
Protocol.SAML11.getServiceParameterName(), Protocol.SAML11.getArtifactParameterName() , false);
Protocol.SAML11.getServiceParameterName(), Protocol.SAML11.getArtifactParameterName(), false);
assertEquals("https://www.myserver.com/hello/hithere/?custom=custom value here&another=good", constructedUrl);
}
@ -246,7 +245,7 @@ public final class CommonUtilsTests extends TestCase {
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null, "www.myserver.com",
Protocol.SAML11.getServiceParameterName(), Protocol.SAML11.getArtifactParameterName() , true);
Protocol.SAML11.getServiceParameterName(), Protocol.SAML11.getArtifactParameterName(), true);
assertEquals("https://www.myserver.com/hello/hithere/?custom=custom+value+here&another=good", constructedUrl);
}
@ -260,7 +259,7 @@ public final class CommonUtilsTests extends TestCase {
request.setServerPort(555);
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null,
serverNameList, "service", "ticket", false);
serverNameList, "service", "ticket", false);
assertEquals(CONST_MY_URL, constructedUrl);
}
@ -280,7 +279,7 @@ public final class CommonUtilsTests extends TestCase {
request.setSecure(true);
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null,
"www.amazon.com www.bestbuy.com www.myserver.com", "service", "ticket", false);
"www.amazon.com www.bestbuy.com www.myserver.com", "service", "ticket", false);
assertEquals(CONST_MY_URL, constructedUrl);
}
@ -292,7 +291,7 @@ public final class CommonUtilsTests extends TestCase {
request.setSecure(true);
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null,
"http://www.amazon.com https://www.bestbuy.com https://www.myserver.com", "service", "ticket", false);
"http://www.amazon.com https://www.bestbuy.com https://www.myserver.com", "service", "ticket", false);
assertEquals(CONST_MY_URL, constructedUrl);
}
@ -303,8 +302,23 @@ public final class CommonUtilsTests extends TestCase {
final String responsedContent = CommonUtils.getResponseFromServer(new URL("http://localhost:8090"), new HttpsURLConnectionFactory(), null);
assertEquals(RESPONSE, responsedContent);
}
public void testUrlEncode() {
assertEquals("this+is+a+very+special+parameter+with+%3D%25%2F", CommonUtils.urlEncode("this is a very special parameter with =%/"));
assertEquals("this+is+a+very+special+parameter+with+%3D%25%2F",
CommonUtils.urlEncode("this is a very special parameter with =%/"));
}
public void testUrlEncodeWithQueryParameters() {
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/idp/authN/ExtCas");
request.setQueryString("conversation=e1s1&ticket=ST-1234-123456789-a&entityId=https://test.edu/sp?alias=1234-1234-1234-1234&something=else");
request.addHeader("Host", "www.myserver.com");
request.setScheme("https");
request.setSecure(true);
final MockHttpServletResponse response = new MockHttpServletResponse();
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null,
"https://my.server.com",
"service", "ticket", false);
assertEquals("https://my.server.com/idp/authN/ExtCas?conversation=e1s1&entityId=https://test.edu/sp?alias=1234-1234-1234-1234&something=else",
constructedUrl);
}
}