Merge branch 'jetty-9.4.x' into jetty-10.0.x
This commit is contained in:
commit
b249021b6d
|
@ -79,10 +79,10 @@ public class WebListenerAnnotation extends DiscoveredAnnotation
|
||||||
HttpSessionAttributeListener.class.isAssignableFrom(clazz) ||
|
HttpSessionAttributeListener.class.isAssignableFrom(clazz) ||
|
||||||
HttpSessionIdListener.class.isAssignableFrom(clazz))
|
HttpSessionIdListener.class.isAssignableFrom(clazz))
|
||||||
{
|
{
|
||||||
java.util.EventListener listener = (java.util.EventListener)_context.getServletContext().createInstance(clazz);
|
|
||||||
MetaData metaData = _context.getMetaData();
|
MetaData metaData = _context.getMetaData();
|
||||||
if (metaData.getOrigin(clazz.getName()+".listener") == Origin.NotSet)
|
if (metaData.getOrigin(clazz.getName()+".listener") == Origin.NotSet)
|
||||||
{
|
{
|
||||||
|
java.util.EventListener listener = (java.util.EventListener)_context.getServletContext().createInstance(clazz);
|
||||||
ListenerHolder h = _context.getServletHandler().newListenerHolder(new Source(Source.Origin.ANNOTATION, clazz.getName()));
|
ListenerHolder h = _context.getServletHandler().newListenerHolder(new Source(Source.Origin.ANNOTATION, clazz.getName()));
|
||||||
h.setListener(listener);
|
h.setListener(listener);
|
||||||
_context.getServletHandler().addListener(h);
|
_context.getServletHandler().addListener(h);
|
||||||
|
|
|
@ -38,7 +38,6 @@ import org.eclipse.jetty.client.util.BufferingResponseListener;
|
||||||
import org.eclipse.jetty.http.HttpField;
|
import org.eclipse.jetty.http.HttpField;
|
||||||
import org.eclipse.jetty.http.HttpHeader;
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
import org.eclipse.jetty.http.QuotedCSV;
|
import org.eclipse.jetty.http.QuotedCSV;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
|
||||||
|
@ -46,16 +45,12 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
||||||
{
|
{
|
||||||
public static final int DEFAULT_MAX_CONTENT_LENGTH = 16*1024;
|
public static final int DEFAULT_MAX_CONTENT_LENGTH = 16*1024;
|
||||||
public static final Logger LOG = Log.getLogger(AuthenticationProtocolHandler.class);
|
public static final Logger LOG = Log.getLogger(AuthenticationProtocolHandler.class);
|
||||||
|
|
||||||
private static final Pattern PARAM_PATTERN = Pattern.compile("([^=]+)=(.*)");
|
|
||||||
private static final Pattern TYPE_PATTERN = Pattern.compile("([^\\s]+)(\\s+(.*))?");
|
|
||||||
private static final Pattern MULTIPLE_CHALLENGE_PATTERN = Pattern.compile("(.*?)\\s*,\\s*([^=\\s,]+(\\s+[^=\\s].*)?)");
|
|
||||||
private static final Pattern BASE64_PATTERN = Pattern.compile("[\\+\\-\\.\\/\\dA-Z_a-z~]+=*");
|
|
||||||
|
|
||||||
private final HttpClient client;
|
private final HttpClient client;
|
||||||
private final int maxContentLength;
|
private final int maxContentLength;
|
||||||
private final ResponseNotifier notifier;
|
private final ResponseNotifier notifier;
|
||||||
|
|
||||||
|
private static final Pattern CHALLENGE_PATTERN = Pattern.compile("(?<schemeOnly>[!#$%&'*+\\-.^_`|~0-9A-Za-z]+)|(?:(?<scheme>[!#$%&'*+\\-.^_`|~0-9A-Za-z]+)\\s+)?(?:(?<token68>[a-zA-Z0-9\\-._~+\\/]+=*)|(?<paramName>[!#$%&'*+\\-.^_`|~0-9A-Za-z]+)\\s*=\\s*(?:(?<paramValue>.*)))");
|
||||||
|
|
||||||
protected AuthenticationProtocolHandler(HttpClient client, int maxContentLength)
|
protected AuthenticationProtocolHandler(HttpClient client, int maxContentLength)
|
||||||
{
|
{
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
@ -84,78 +79,49 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected List<HeaderInfo> getHeaderInfo(String header) throws IllegalArgumentException
|
||||||
protected List<HeaderInfo> getHeaderInfo(String value) throws IllegalArgumentException
|
|
||||||
{
|
{
|
||||||
String header = value;
|
|
||||||
List<HeaderInfo> headerInfos = new ArrayList<>();
|
List<HeaderInfo> headerInfos = new ArrayList<>();
|
||||||
|
Matcher m;
|
||||||
|
|
||||||
while(true)
|
for(String value : new QuotedCSV(true, header))
|
||||||
{
|
{
|
||||||
Matcher m = MULTIPLE_CHALLENGE_PATTERN.matcher(header);
|
m = CHALLENGE_PATTERN.matcher(value);
|
||||||
if (m.matches())
|
if (m.matches())
|
||||||
{
|
{
|
||||||
headerInfos.add(newHeaderInfo(m.group(1)));
|
if(m.group("schemeOnly") != null)
|
||||||
header = m.group(2);
|
{
|
||||||
}
|
headerInfos.add(new HeaderInfo(getAuthorizationHeader(), m.group(1), new HashMap<>()));
|
||||||
else
|
continue;
|
||||||
{
|
}
|
||||||
headerInfos.add(newHeaderInfo(header));
|
|
||||||
break;
|
if (m.group("scheme") != null)
|
||||||
|
{
|
||||||
|
headerInfos.add(new HeaderInfo(getAuthorizationHeader(), m.group("scheme"), new HashMap<>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headerInfos.isEmpty())
|
||||||
|
throw new IllegalArgumentException("Parameters without auth-scheme");
|
||||||
|
|
||||||
|
Map<String, String> authParams = headerInfos.get(headerInfos.size() - 1).getParameters();
|
||||||
|
if (m.group("paramName") != null)
|
||||||
|
{
|
||||||
|
String paramVal = QuotedCSV.unquote(m.group("paramValue"));
|
||||||
|
authParams.put(m.group("paramName"), paramVal);
|
||||||
|
}
|
||||||
|
else if (m.group("token68") != null)
|
||||||
|
{
|
||||||
|
if (!authParams.isEmpty())
|
||||||
|
throw new IllegalArgumentException("token68 after auth-params");
|
||||||
|
|
||||||
|
authParams.put("base64", m.group("token68"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return headerInfos;
|
return headerInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HeaderInfo newHeaderInfo(String value) throws IllegalArgumentException
|
|
||||||
{
|
|
||||||
String type;
|
|
||||||
Map<String,String> params = new HashMap<>();
|
|
||||||
|
|
||||||
Matcher m = TYPE_PATTERN.matcher(value);
|
|
||||||
if (m.matches())
|
|
||||||
{
|
|
||||||
type = m.group(1);
|
|
||||||
if (m.group(2) != null)
|
|
||||||
params = parseParameters(m.group(3));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("Invalid Authentication Format");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new HeaderInfo(getAuthorizationHeader(), type, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Map<String, String> parseParameters(String wwwAuthenticate) throws IllegalArgumentException
|
|
||||||
{
|
|
||||||
Map<String, String> result = new HashMap<>();
|
|
||||||
|
|
||||||
Matcher b64 = BASE64_PATTERN.matcher(wwwAuthenticate);
|
|
||||||
if (b64.matches())
|
|
||||||
{
|
|
||||||
result.put("base64", wwwAuthenticate);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QuotedCSV parts = new QuotedCSV(false, wwwAuthenticate);
|
|
||||||
for (String part : parts)
|
|
||||||
{
|
|
||||||
Matcher params = PARAM_PATTERN.matcher(part);
|
|
||||||
if (params.matches())
|
|
||||||
{
|
|
||||||
String name = StringUtil.asciiToLowerCase(params.group(1));
|
|
||||||
String value = (params.group(2)==null) ? "" : params.group(2);
|
|
||||||
result.put(name, value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("Invalid Authentication Format");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AuthenticationListener extends BufferingResponseListener
|
private class AuthenticationListener extends BufferingResponseListener
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,12 +31,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.IntFunction;
|
import java.util.function.IntFunction;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.api.Authentication;
|
import org.eclipse.jetty.client.api.Authentication;
|
||||||
|
import org.eclipse.jetty.client.api.Authentication.HeaderInfo;
|
||||||
import org.eclipse.jetty.client.api.AuthenticationStore;
|
import org.eclipse.jetty.client.api.AuthenticationStore;
|
||||||
import org.eclipse.jetty.client.api.ContentProvider;
|
import org.eclipse.jetty.client.api.ContentProvider;
|
||||||
import org.eclipse.jetty.client.api.ContentResponse;
|
import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
|
@ -44,7 +44,6 @@ import org.eclipse.jetty.client.api.Request;
|
||||||
import org.eclipse.jetty.client.api.Response;
|
import org.eclipse.jetty.client.api.Response;
|
||||||
import org.eclipse.jetty.client.api.Response.Listener;
|
import org.eclipse.jetty.client.api.Response.Listener;
|
||||||
import org.eclipse.jetty.client.api.Result;
|
import org.eclipse.jetty.client.api.Result;
|
||||||
import org.eclipse.jetty.client.api.Authentication.HeaderInfo;
|
|
||||||
import org.eclipse.jetty.client.util.BasicAuthentication;
|
import org.eclipse.jetty.client.util.BasicAuthentication;
|
||||||
import org.eclipse.jetty.client.util.DeferredContentProvider;
|
import org.eclipse.jetty.client.util.DeferredContentProvider;
|
||||||
import org.eclipse.jetty.client.util.DigestAuthentication;
|
import org.eclipse.jetty.client.util.DigestAuthentication;
|
||||||
|
@ -705,7 +704,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
||||||
Assert.assertTrue(headerInfo.getParameter("name").equals("value"));
|
Assert.assertTrue(headerInfo.getParameter("name").equals("value"));
|
||||||
Assert.assertTrue(headerInfo.getParameter("other").equals("value2"));
|
Assert.assertTrue(headerInfo.getParameter("other").equals("value2"));
|
||||||
|
|
||||||
headerInfos = aph.getHeaderInfo("Scheme name=value, Scheme2 name=value2");
|
headerInfos = aph.getHeaderInfo(", , , , ,,,Scheme name=value, ,,Scheme2 name=value2,, ,,");
|
||||||
Assert.assertEquals(headerInfos.size(), 2);
|
Assert.assertEquals(headerInfos.size(), 2);
|
||||||
Assert.assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Scheme"));
|
Assert.assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Scheme"));
|
||||||
Assert.assertTrue(headerInfos.get(0).getParameter("nAmE").equals("value"));
|
Assert.assertTrue(headerInfos.get(0).getParameter("nAmE").equals("value"));
|
||||||
|
@ -768,4 +767,23 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
||||||
Assert.assertTrue(headerInfoList.get(2).getParameter("realm").equals("thermostat3="));
|
Assert.assertTrue(headerInfoList.get(2).getParameter("realm").equals("thermostat3="));
|
||||||
Assert.assertTrue(headerInfoList.get(2).getParameter("nonce").equals("9523570528="));
|
Assert.assertTrue(headerInfoList.get(2).getParameter("nonce").equals("9523570528="));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleChallangeLooksLikeMultipleChallenge()
|
||||||
|
{
|
||||||
|
AuthenticationProtocolHandler aph = new WWWAuthenticationProtocolHandler(client);
|
||||||
|
List<HeaderInfo> headerInfoList = aph.getHeaderInfo("Digest param=\",f \"");
|
||||||
|
Assert.assertEquals(1, headerInfoList.size());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
headerInfoList = aph.getHeaderInfo("Digest realm=\"thermostat\", qop=\",Digest realm=hello\", nonce=\"1523430383=\"");
|
||||||
|
Assert.assertEquals(1, headerInfoList.size());
|
||||||
|
|
||||||
|
HeaderInfo headerInfo = headerInfoList.get(0);
|
||||||
|
Assert.assertTrue(headerInfo.getType().equalsIgnoreCase("Digest"));
|
||||||
|
Assert.assertTrue(headerInfo.getParameter("qop").equals(",Digest realm=hello"));
|
||||||
|
Assert.assertTrue(headerInfo.getParameter("realm").equals("thermostat"));
|
||||||
|
Assert.assertThat(headerInfo.getParameter("nonce"), Matchers.is("1523430383="));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,6 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<mainClass>org.eclipse.jetty.http2.server.H2SpecServer</mainClass>
|
<mainClass>org.eclipse.jetty.http2.server.H2SpecServer</mainClass>
|
||||||
<skip>${skipTests}</skip>
|
<skip>${skipTests}</skip>
|
||||||
<!-- TODO: remove the exclusion when upgrading to h2spec 2.1.1+ -->
|
|
||||||
<excludeSpecs>
|
|
||||||
<excludeSpec>5.1 - closed: Sends a DATA frame</excludeSpec>
|
|
||||||
</excludeSpecs>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
|
|
|
@ -62,4 +62,13 @@ public class ListenerHolder extends BaseHolder<EventListener>
|
||||||
|
|
||||||
super.doStart();
|
super.doStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return super.toString()+(_listener == null?"":": "+getClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,7 +190,7 @@ public class GzipHandlerTest
|
||||||
for (Enumeration<String> e = req.getParameterNames(); e.hasMoreElements(); )
|
for (Enumeration<String> e = req.getParameterNames(); e.hasMoreElements(); )
|
||||||
{
|
{
|
||||||
String n = e.nextElement();
|
String n = e.nextElement();
|
||||||
response.getWriter().printf("%s: %s%n",n,req.getParameter(n));
|
response.getWriter().printf("%s: %s\n",n,req.getParameter(n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,7 @@ public class WebSocketPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time in ms (milliseconds) that a websocket connection mad by idle before being closed automatically.
|
* The time in ms (milliseconds) that a websocket connection may by idle before being closed automatically.
|
||||||
*
|
*
|
||||||
* @return the timeout in milliseconds for idle timeout.
|
* @return the timeout in milliseconds for idle timeout.
|
||||||
*/
|
*/
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -893,7 +893,7 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.github.madgnome</groupId>
|
<groupId>com.github.madgnome</groupId>
|
||||||
<artifactId>h2spec-maven-plugin</artifactId>
|
<artifactId>h2spec-maven-plugin</artifactId>
|
||||||
<version>0.3</version>
|
<version>0.4</version>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</pluginManagement>
|
</pluginManagement>
|
||||||
|
|
Loading…
Reference in New Issue