Issue #2909 - Replace B64Code with java.util.Base64

+ Deprecated B64Code
+ All code that isn't B64CodeTest is now using java.util.Base64
+ B64CodeTest is updated to confirm change to java.util.Base64
  is possible without change in behavior. Just have to make
  sure you use the appropriate Encoder / Decoder for the task
  at hand (default vs mime vs url)

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
This commit is contained in:
Joakim Erdfelt 2019-05-09 07:41:52 -05:00 committed by Greg Wilkins
parent 8e4756b89c
commit b44ecc932a
28 changed files with 299 additions and 220 deletions

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.client.util;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.AuthenticationStore;
@ -27,7 +28,6 @@ import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.B64Code;
/**
* Implementation of the HTTP "Basic" authentication defined in RFC 2617.
@ -91,7 +91,8 @@ public class BasicAuthentication extends AbstractAuthentication
{
this.uri = uri;
this.header = header;
this.value = "Basic " + B64Code.encode(user + ":" + password, StandardCharsets.ISO_8859_1);
byte[] authBytes = (user + ":" + password).getBytes(StandardCharsets.ISO_8859_1);
this.value = "Basic " + Base64.getEncoder().encodeToString(authBytes);
}
@Override

View File

@ -21,9 +21,9 @@ package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -35,7 +35,6 @@ import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.B64Code;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
@ -82,7 +81,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest
{
final String user = "foo";
final String password = "bar";
final String credentials = B64Code.encode(user + ":" + password, StandardCharsets.ISO_8859_1);
final String credentials = Base64.getEncoder().encodeToString((user + ":" + password).getBytes(StandardCharsets.ISO_8859_1));
final String serverHost = "server";
final String realm = "test_realm";
final int status = HttpStatus.NO_CONTENT_204;
@ -162,7 +161,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest
{
String user = "foo";
String password = "bar";
String credentials = B64Code.encode(user + ":" + password, StandardCharsets.ISO_8859_1);
String credentials = Base64.getEncoder().encodeToString((user + ":" + password).getBytes(StandardCharsets.ISO_8859_1));
String proxyHost = "localhost";
String serverHost = "server";
int serverPort = HttpScheme.HTTP.is(scenario.getScheme()) ? 80 : 443;

View File

@ -18,6 +18,24 @@
package org.eclipse.jetty.http;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Part;
import org.eclipse.jetty.http.MultiPartFormInputStream.MultiPart;
import org.eclipse.jetty.util.IO;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
@ -33,24 +51,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Part;
import org.eclipse.jetty.http.MultiPartFormInputStream.MultiPart;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.IO;
import org.junit.jupiter.api.Test;
/**
* MultiPartInputStreamTest
*/
@ -862,7 +862,7 @@ public class MultiPartFormInputStreamTest
"Content-Transfer-Encoding: base64\r\n" +
"Content-Type: application/octet-stream\r\n" +
"\r\n" +
B64Code.encode("hello jetty") + "\r\n" +
Base64.getEncoder().encodeToString("hello jetty".getBytes(ISO_8859_1)) + "\r\n" +
"--AaB03x\r\n" +
"Content-disposition: form-data; name=\"final\"\r\n" +
"Content-Type: text/plain\r\n" +
@ -889,7 +889,7 @@ public class MultiPartFormInputStreamTest
assertNotNull(p2);
baos = new ByteArrayOutputStream();
IO.copy(p2.getInputStream(), baos);
assertEquals(B64Code.encode("hello jetty"), baos.toString("US-ASCII"));
assertEquals(Base64.getEncoder().encodeToString("hello jetty".getBytes(ISO_8859_1)), baos.toString("US-ASCII"));
Part p3 = mpis.getPart("final");
assertNotNull(p3);

View File

@ -23,6 +23,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@ -55,7 +56,6 @@ import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.CountingCallback;
@ -333,7 +333,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
if (settingsField == null)
throw new BadMessageException("Missing " + HttpHeader.HTTP2_SETTINGS + " header");
String value = settingsField.getValue();
final byte[] settings = B64Code.decodeRFC4648URL(value == null ? "" : value);
final byte[] settings = Base64.getUrlDecoder().decode(value == null ? "" : value);
if (LOG.isDebugEnabled())
LOG.debug("{} settings {}",this,TypeUtil.toHexString(settings));

View File

@ -20,12 +20,12 @@ package org.eclipse.jetty.jaas.spi;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
@ -45,7 +45,6 @@ import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import org.eclipse.jetty.jaas.callback.ObjectCallback;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -755,13 +754,13 @@ public class LdapLoginModule extends AbstractLoginModule
private static String base64ToHex(String src)
{
byte[] bytes = B64Code.decode(src);
byte[] bytes = Base64.getDecoder().decode(src);
return TypeUtil.toString(bytes, 16);
}
private static String hexToBase64(String src)
{
byte[] bytes = TypeUtil.fromHexString(src);
return new String(B64Code.encode(bytes));
return Base64.getEncoder().encodeToString(bytes);
}
}

View File

@ -20,9 +20,9 @@ package org.eclipse.jetty.security.jaspi.modules;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import java.util.Set;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
@ -41,7 +41,6 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.security.authentication.LoginCallbackImpl;
import org.eclipse.jetty.security.jaspi.JaspiMessageInfo;
import org.eclipse.jetty.security.jaspi.callback.CredentialValidationCallback;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.security.Credential;
import org.eclipse.jetty.util.security.Password;
@ -120,7 +119,7 @@ public class BaseAuthModule implements ServerAuthModule, ServerAuthContext
throws IOException, UnsupportedCallbackException
{
credentials = credentials.substring(credentials.indexOf(' ')+1);
credentials = B64Code.decode(credentials, StandardCharsets.ISO_8859_1);
credentials = new String(Base64.getDecoder().decode(credentials), StandardCharsets.ISO_8859_1);
int i = credentials.indexOf(':');
String userName = credentials.substring(0,i);
String password = credentials.substring(i+1);

View File

@ -20,7 +20,7 @@ package org.eclipse.jetty.security.jaspi.modules;
import java.io.IOException;
import java.security.Principal;
import java.util.Base64;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
@ -30,7 +30,6 @@ import javax.security.auth.message.MessageInfo;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Password;
@ -69,7 +68,7 @@ public class ClientCertAuthModule extends BaseAuthModule
if (principal == null) principal = certs[0].getIssuerDN();
final String username = principal == null ? "clientcert" : principal.getName();
// TODO no idea if this is correct
final String password = new String(B64Code.encode(certs[0].getSignature()));
final String password = Base64.getEncoder().encodeToString(certs[0].getSignature());
// TODO is cert_auth correct?
if (login(clientSubject, username, new Password(password), Constraint.__CERT_AUTH, messageInfo)) { return AuthStatus.SUCCESS; }

View File

@ -21,8 +21,8 @@ package org.eclipse.jetty.security.jaspi.modules;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
@ -34,7 +34,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
@ -205,7 +204,7 @@ public class DigestAuthModule extends BaseAuthModule
if (i == 23) break;
}
return new String(B64Code.encode(nounce));
return Base64.getEncoder().encodeToString(nounce);
}
/**
@ -217,7 +216,7 @@ public class DigestAuthModule extends BaseAuthModule
{
try
{
byte[] n = B64Code.decode(nonce.toCharArray());
byte[] n = Base64.getDecoder().decode(nonce);
if (n.length != 24) return -1;
long ts = 0;

View File

@ -18,13 +18,10 @@
package org.eclipse.jetty.security.jaspi;
import static org.hamcrest.Matchers.startsWith;
import static org.hamcrest.MatcherAssert.assertThat;
import java.io.IOException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -38,7 +35,6 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Credential;
import org.eclipse.jetty.util.security.Password;
@ -47,6 +43,10 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.startsWith;
public class JaspiTest
{
Server _server;
@ -163,7 +163,8 @@ public class JaspiTest
public void testConstraintWrongAuth() throws Exception
{
String response = _connector.getResponse("GET /ctx/jaspi/test HTTP/1.0\n" +
"Authorization: Basic " + B64Code.encode("user:wrong") + "\n\n");
"Authorization: Basic " + Base64.getEncoder().encodeToString("user:wrong".getBytes(ISO_8859_1)) +
"\n\n");
assertThat(response,startsWith("HTTP/1.1 401 Unauthorized"));
assertThat(response,Matchers.containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
}
@ -172,7 +173,8 @@ public class JaspiTest
public void testConstraintAuth() throws Exception
{
String response = _connector.getResponse("GET /ctx/jaspi/test HTTP/1.0\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\n\n");
"Authorization: Basic " + Base64.getEncoder().encodeToString("user:password".getBytes(ISO_8859_1)) +
"\n\n");
assertThat(response,startsWith("HTTP/1.1 200 OK"));
}

View File

@ -28,6 +28,7 @@ import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Locale;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.ServletException;
@ -43,13 +44,13 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.Net;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -280,7 +281,7 @@ public class ConnectHandlerTest extends AbstractConnectHandlerTest
return false;
}
String b64 = proxyAuthorization.substring("Basic ".length());
String credentials = B64Code.decode(b64, StandardCharsets.UTF_8);
String credentials = new String(Base64.getDecoder().decode(b64), StandardCharsets.UTF_8);
return "test:test".equals(credentials);
}
};
@ -314,7 +315,7 @@ public class ConnectHandlerTest extends AbstractConnectHandlerTest
}
// Try with authentication
String credentials = "Basic " + B64Code.encode("test:test");
String credentials = "Basic " + Base64.getEncoder().encodeToString("test:test".getBytes(ISO_8859_1));
request = "" +
"CONNECT " + hostPort + " HTTP/1.1\r\n" +
"Host: " + hostPort + "\r\n" +

View File

@ -18,13 +18,12 @@
package org.eclipse.jetty.security;
import java.util.Base64;
import java.util.Properties;
import javax.security.auth.Subject;
import javax.servlet.ServletRequest;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -121,7 +120,7 @@ public class SpnegoLoginService extends AbstractLifeCycle implements LoginServic
{
String encodedAuthToken = (String)credentials;
byte[] authToken = B64Code.decode(encodedAuthToken);
byte[] authToken = Base64.getDecoder().decode(encodedAuthToken);
GSSManager manager = GSSManager.getInstance();
try

View File

@ -20,7 +20,7 @@ package org.eclipse.jetty.security.authentication;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
@ -32,7 +32,6 @@ import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Authentication.User;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.security.Constraint;
/**
@ -82,7 +81,7 @@ public class BasicAuthenticator extends LoginAuthenticator
if ("basic".equalsIgnoreCase(method))
{
credentials = credentials.substring(space+1);
credentials = B64Code.decode(credentials, StandardCharsets.ISO_8859_1);
credentials = new String(Base64.getDecoder().decode(credentials), StandardCharsets.ISO_8859_1);
int i = credentials.indexOf(':');
if (i>0)
{

View File

@ -23,8 +23,8 @@ import java.security.KeyStore;
import java.security.Principal;
import java.security.cert.CRL;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Collection;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
@ -35,7 +35,6 @@ import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Authentication.User;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.CertificateUtils;
import org.eclipse.jetty.util.security.CertificateValidator;
@ -115,7 +114,8 @@ public class ClientCertAuthenticator extends LoginAuthenticator
if (principal == null) principal = cert.getIssuerDN();
final String username = principal == null ? "clientcert" : principal.getName();
final char[] credential = B64Code.encode(cert.getSignature());
// TODO: investigate if using a raw byte[] is better vs older char[]
final char[] credential = Base64.getEncoder().encodeToString(cert.getSignature()).toCharArray();
UserIdentity user = login(username, credential, req);
if (user!=null)

View File

@ -22,13 +22,13 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.BitSet;
import java.util.Objects;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
@ -42,7 +42,6 @@ import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Authentication.User;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
@ -233,7 +232,7 @@ public class DigestAuthenticator extends LoginAuthenticator
byte[] nounce = new byte[24];
_random.nextBytes(nounce);
nonce = new Nonce(new String(B64Code.encode(nounce)), request.getTimeStamp(), getMaxNonceCount());
nonce = new Nonce(Base64.getEncoder().encodeToString(nounce), request.getTimeStamp(), getMaxNonceCount());
}
while (_nonceMap.putIfAbsent(nonce._nonce, nonce) != null);
_nonceQueue.add(nonce);

View File

@ -19,10 +19,10 @@
package org.eclipse.jetty.security;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -60,7 +60,6 @@ import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.security.Constraint;
@ -72,6 +71,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.in;
@ -497,7 +497,7 @@ public class ConstraintTest
scenarios.add(Arguments.of(
new Scenario(
"GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user:wrong") + "\r\n" +
"Authorization: Basic " + authBase64("user:wrong") + "\r\n" +
"\r\n",
HttpStatus.UNAUTHORIZED_401,
(response) -> {
@ -508,7 +508,7 @@ public class ConstraintTest
));
// rawResponse = _connector.getResponse("GET /ctx/auth/info HTTP/1.0\r\n" +
// "Authorization: Basic " + B64Code.encode("user:wrong") + "\r\n" +
// "Authorization: Basic " + authBase64("user:wrong") + "\r\n" +
// "\r\n");
// assertThat(rawResponse, startsWith("HTTP/1.1 401 Unauthorized"));
// assertThat(rawResponse, containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
@ -516,14 +516,14 @@ public class ConstraintTest
scenarios.add(Arguments.of(
new Scenario(
"GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"Authorization: Basic " + authBase64("user:password") + "\r\n" +
"\r\n",
HttpStatus.OK_200
)
));
// rawResponse = _connector.getResponse("GET /ctx/auth/info HTTP/1.0\r\n" +
// "Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
// "Authorization: Basic " + authBase64("user:password") + "\r\n" +
// "\r\n");
// assertThat(rawResponse, startsWith("HTTP/1.1 200 OK"));
@ -546,7 +546,7 @@ public class ConstraintTest
scenarios.add(Arguments.of(
new Scenario(
"GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("admin:wrong") + "\r\n" +
"Authorization: Basic " + authBase64("admin:wrong") + "\r\n" +
"\r\n",
HttpStatus.UNAUTHORIZED_401,
(response) -> {
@ -559,7 +559,7 @@ public class ConstraintTest
scenarios.add(Arguments.of(
new Scenario(
"GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"Authorization: Basic " + authBase64("user:password") + "\r\n" +
"\r\n",
HttpStatus.FORBIDDEN_403,
(response) -> {
@ -572,7 +572,7 @@ public class ConstraintTest
scenarios.add(Arguments.of(
new Scenario(
"GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("admin:password") + "\r\n" +
"Authorization: Basic " + authBase64("admin:password") + "\r\n" +
"\r\n",
HttpStatus.OK_200)
));
@ -588,7 +588,7 @@ public class ConstraintTest
scenarios.add(Arguments.of(
new Scenario(
"GET /ctx/omit/x HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("admin:password") + "\r\n" +
"Authorization: Basic " + authBase64("admin:password") + "\r\n" +
"\r\n",
HttpStatus.OK_200
@ -599,7 +599,7 @@ public class ConstraintTest
scenarios.add(Arguments.of(
new Scenario(
"POST /ctx/omit/x HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
"Authorization: Basic " + authBase64("user2:password") + "\r\n" +
"\r\n", HttpStatus.OK_200)
));
@ -607,7 +607,7 @@ public class ConstraintTest
scenarios.add(Arguments.of(
new Scenario(
"POST /ctx/omit/x HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user3:password") + "\r\n" +
"Authorization: Basic " + authBase64("user3:password") + "\r\n" +
"\r\n",
HttpStatus.OK_200)
));
@ -616,7 +616,7 @@ public class ConstraintTest
scenarios.add(Arguments.of(
new Scenario(
"HEAD /ctx/omit/x HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
"Authorization: Basic " + authBase64("user2:password") + "\r\n" +
"\r\n",
HttpStatus.FORBIDDEN_403)
));
@ -689,17 +689,17 @@ public class ConstraintTest
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] ha1;
// calc A1 digest
md.update(username.getBytes(StandardCharsets.ISO_8859_1));
md.update(username.getBytes(ISO_8859_1));
md.update((byte) ':');
md.update("TestRealm".getBytes(StandardCharsets.ISO_8859_1));
md.update("TestRealm".getBytes(ISO_8859_1));
md.update((byte) ':');
md.update(password.getBytes(StandardCharsets.ISO_8859_1));
md.update(password.getBytes(ISO_8859_1));
ha1 = md.digest();
// calc A2 digest
md.reset();
md.update("GET".getBytes(StandardCharsets.ISO_8859_1));
md.update("GET".getBytes(ISO_8859_1));
md.update((byte) ':');
md.update(uri.getBytes(StandardCharsets.ISO_8859_1));
md.update(uri.getBytes(ISO_8859_1));
byte[] ha2 = md.digest();
// calc digest
@ -709,17 +709,17 @@ public class ConstraintTest
// request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2)
// ) > <">
md.update(TypeUtil.toString(ha1, 16).getBytes(StandardCharsets.ISO_8859_1));
md.update(TypeUtil.toString(ha1, 16).getBytes(ISO_8859_1));
md.update((byte) ':');
md.update(nonce.getBytes(StandardCharsets.ISO_8859_1));
md.update(nonce.getBytes(ISO_8859_1));
md.update((byte) ':');
md.update(nc.getBytes(StandardCharsets.ISO_8859_1));
md.update(nc.getBytes(ISO_8859_1));
md.update((byte) ':');
md.update(CNONCE.getBytes(StandardCharsets.ISO_8859_1));
md.update(CNONCE.getBytes(ISO_8859_1));
md.update((byte) ':');
md.update("auth".getBytes(StandardCharsets.ISO_8859_1));
md.update("auth".getBytes(ISO_8859_1));
md.update((byte) ':');
md.update(TypeUtil.toString(ha2, 16).getBytes(StandardCharsets.ISO_8859_1));
md.update(TypeUtil.toString(ha2, 16).getBytes(ISO_8859_1));
byte[] digest = md.digest();
// check digest
@ -1241,18 +1241,18 @@ public class ConstraintTest
assertThat(response, containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponse("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user:wrong") + "\r\n" +
"Authorization: Basic " + authBase64("user:wrong") + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 401 Unauthorized"));
assertThat(response, containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponse("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user3:password") + "\r\n" +
"Authorization: Basic " + authBase64("user3:password") + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 403"));
response = _connector.getResponse("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
"Authorization: Basic " + authBase64("user2:password") + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
@ -1263,20 +1263,20 @@ public class ConstraintTest
assertThat(response, containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponse("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("admin:wrong") + "\r\n" +
"Authorization: Basic " + authBase64("admin:wrong") + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 401 Unauthorized"));
assertThat(response, containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponse("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"Authorization: Basic " + authBase64("user:password") + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 403 "));
assertThat(response, containsString("!role"));
response = _connector.getResponse("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("admin:password") + "\r\n" +
"Authorization: Basic " + authBase64("admin:password") + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
@ -1597,7 +1597,7 @@ public class ConstraintTest
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
rawResponse = _connector.getResponse("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
"Authorization: Basic " + authBase64("user2:password") + "\r\n" +
"\r\n", 100000, TimeUnit.MILLISECONDS);
response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.INTERNAL_SERVER_ERROR_500));
@ -1612,7 +1612,7 @@ public class ConstraintTest
_server.start();
rawResponse = _connector.getResponse("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
"Authorization: Basic " + authBase64("user2:password") + "\r\n" +
"\r\n", 100000, TimeUnit.MILLISECONDS);
response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
@ -1632,13 +1632,13 @@ public class ConstraintTest
assertThat(response, containsString("user=null"));
response = _connector.getResponse("GET /ctx/noauth/info HTTP/1.0\r\n"+
"Authorization: Basic " + B64Code.encode("admin:wrong") + "\r\n" +
"Authorization: Basic " + authBase64("admin:wrong") + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=null"));
response = _connector.getResponse("GET /ctx/noauth/info HTTP/1.0\r\n"+
"Authorization: Basic " + B64Code.encode("admin:password") + "\r\n" +
"Authorization: Basic " + authBase64("admin:password") + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=admin"));
@ -1660,6 +1660,13 @@ public class ConstraintTest
response = _connector.getResponse("GET /ctx/forbid/post HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 200 ")); // This is so stupid, but it is the S P E C
}
private static String authBase64(String authorization)
{
byte raw[] = authorization.getBytes(ISO_8859_1);
return Base64.getEncoder().encodeToString(raw);
}
private class RequestHandler extends AbstractHandler
{
@Override

View File

@ -18,16 +18,11 @@
package org.eclipse.jetty.security;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -40,7 +35,6 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Password;
import org.junit.jupiter.api.AfterEach;
@ -48,6 +42,12 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @version $Revision: 1441 $ $Date: 2010-04-02 12:28:17 +0200 (Fri, 02 Apr 2010) $
*/
@ -297,37 +297,41 @@ public class SpecExampleConstraintTest
response = _connector.getResponse("HEAD /ctx/index.html HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
Base64.Encoder authEncoder = Base64.getEncoder();
String encodedHarry = authEncoder.encodeToString("harry:password".getBytes(ISO_8859_1));
String encodedChris = authEncoder.encodeToString("chris:password".getBytes(ISO_8859_1));
response = _connector.getResponse("HEAD /ctx/index.html HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("harry:password") + "\r\n" +
"Authorization: Basic " + encodedHarry + "\r\n" +
"\r\n");
assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
response = _connector.getResponse("HEAD /ctx/acme/wholesale/index.html HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("harry:password") + "\r\n" +
"Authorization: Basic " + encodedHarry + "\r\n" +
"\r\n");
assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
response = _connector.getResponse("HEAD /ctx/acme/retail/index.html HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("harry:password") + "\r\n" +
"Authorization: Basic " + encodedHarry + "\r\n" +
"\r\n");
assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
//a user in role CONTRACTOR can do a GET
response = _connector.getResponse("GET /ctx/acme/wholesale/index.html HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("chris:password") + "\r\n" +
"Authorization: Basic " + encodedChris + "\r\n" +
"\r\n");
assertThat(response,startsWith("HTTP/1.1 200 OK"));
//a user in role CONTRACTOR can only do a post if confidential
response = _connector.getResponse("POST /ctx/acme/wholesale/index.html HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("chris:password") + "\r\n" +
"Authorization: Basic " + encodedChris + "\r\n" +
"\r\n");
assertThat(response,startsWith("HTTP/1.1 403 !"));
//a user in role HOMEOWNER can do a GET
response = _connector.getResponse("GET /ctx/acme/retail/index.html HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("harry:password") + "\r\n" +
"Authorization: Basic " + encodedHarry + "\r\n" +
"\r\n");
assertThat(response,startsWith("HTTP/1.1 200 OK"));
}

View File

@ -23,6 +23,7 @@ import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.util.Base64;
/** Fast B64 Encoder/Decoder as described in RFC 1421.
@ -30,8 +31,9 @@ import java.nio.charset.UnsupportedCharsetException;
* 1521. If you require this you must pre/post process your data.
* <p> Note that in a web context the usual case is to not want
* linebreaks or other white space in the encoded output.
*
* @deprecated use {@link java.util.Base64} instead
*/
@Deprecated
public class B64Code
{
private static final char __pad='=';
@ -82,9 +84,11 @@ public class B64Code
* <p>Does not insert whitespace as described in RFC 1521.
* @param s String to encode.
* @return String containing the encoded form of the input.
* @deprecated use {@link Base64.Encoder#encodeToString(byte[])}} instead.
*/
public static String encode(String s)
{
// FIXME: no Jetty mainline code uses this anymore
return encode(s, (Charset)null);
}
@ -98,6 +102,7 @@ public class B64Code
*/
public static String encode(String s,String charEncoding)
{
// FIXME: no Jetty mainline code uses this anymore
byte[] bytes;
if (charEncoding==null)
bytes=s.getBytes(StandardCharsets.ISO_8859_1);
@ -115,6 +120,7 @@ public class B64Code
*/
public static String encode(String s, Charset charEncoding)
{
// FIXME: no Jetty mainline code uses this anymore
byte[] bytes=s.getBytes(charEncoding==null ? StandardCharsets.ISO_8859_1 : charEncoding);
return new String(encode(bytes));
}
@ -128,6 +134,7 @@ public class B64Code
*/
public static char[] encode(byte[] b)
{
// FIXME: no Jetty mainline code uses this anymore
if (b==null)
return null;
@ -188,6 +195,7 @@ public class B64Code
*/
public static char[] encode(byte[] b, boolean rfc2045)
{
// FIXME: no Jetty mainline code uses this anymore
if (b==null)
return null;
if (!rfc2045)
@ -265,6 +273,7 @@ public class B64Code
@SuppressWarnings("DefaultCharset")
public static String decode(String encoded,String charEncoding)
{
// FIXME: no Jetty mainline code uses this anymore
byte[] decoded=decode(encoded);
if (charEncoding==null)
return new String(decoded);
@ -285,6 +294,7 @@ public class B64Code
@SuppressWarnings("DefaultCharset")
public static String decode(String encoded, Charset charEncoding)
{
// FIXME: no Jetty mainline code uses this anymore
byte[] decoded=decode(encoded);
if (charEncoding==null)
return new String(decoded);
@ -305,6 +315,7 @@ public class B64Code
*/
public static byte[] decode(char[] b)
{
// FIXME: no Jetty mainline code uses this anymore
if (b==null)
return null;
@ -388,6 +399,7 @@ public class B64Code
*/
public static byte[] decode(String encoded)
{
// FIXME: no Jetty mainline code uses this anymore
if (encoded==null)
return null;
@ -407,6 +419,7 @@ public class B64Code
*/
static public void decode(String encoded, ByteArrayOutputStream bout)
{
// FIXME: no Jetty mainline code uses this anymore
if (encoded==null)
return;
@ -457,6 +470,7 @@ public class B64Code
/* ------------------------------------------------------------ */
public static byte[] decodeRFC4648URL(String encoded)
{
// FIXME: no Jetty mainline code uses this anymore
if (encoded==null)
return null;
@ -476,6 +490,7 @@ public class B64Code
*/
static public void decodeRFC4648URL (String encoded, ByteArrayOutputStream bout)
{
// FIXME: no Jetty mainline code uses this anymore
if (encoded==null)
return;
@ -523,20 +538,20 @@ public class B64Code
return;
}
public static void encode(int value,Appendable buf) throws IOException
{
// FIXME: no Jetty mainline code uses this anymore
buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]);
buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]);
buf.append(__rfc1421alphabet[0x3f&((0x000FC000&value)>>14)]);
buf.append(__rfc1421alphabet[0x3f&((0x00003F00&value)>>8)]);
buf.append(__rfc1421alphabet[0x3f&((0x000000FC&value)>>2)]);
buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4)]);
buf.append('=');
}
public static void encode(long lvalue,Appendable buf) throws IOException
{
// FIXME: no Jetty mainline code uses this anymore
int value=(int)(0xFFFFFFFC&(lvalue>>32));
buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]);
buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]);

View File

@ -34,6 +34,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
@ -934,14 +935,14 @@ public class MultiPartInputStreamParser
}
// TODO: considers switching to Base64.getMimeDecoder().wrap(InputStream)
private static class Base64InputStream extends InputStream
{
ReadLineInputStream _in;
String _line;
byte[] _buffer;
int _pos;
Base64.Decoder base64Decoder = Base64.getDecoder();
public Base64InputStream(ReadLineInputStream rlis)
{
@ -967,7 +968,7 @@ public class MultiPartInputStreamParser
else
{
ByteArrayOutputStream baos = new ByteArrayOutputStream((4*_line.length()/3)+2);
B64Code.decode(_line, baos);
baos.write(base64Decoder.decode(_line));
baos.write(13);
baos.write(10);
_buffer = baos.toByteArray();

View File

@ -31,12 +31,12 @@ import java.nio.channels.ReadableByteChannel;
import java.nio.file.Path;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.MultiMap;
@ -956,8 +956,6 @@ public abstract class Resource implements ResourceFactory, Closeable
}
public String getWeakETag(String suffix)
{
try
{
StringBuilder b = new StringBuilder(32);
b.append("W/\"");
@ -968,16 +966,23 @@ public abstract class Resource implements ResourceFactory, Closeable
for (int i=0; i<length;i++)
lhash=31*lhash+name.charAt(i);
B64Code.encode(lastModified()^lhash,b);
B64Code.encode(length()^lhash,b);
Base64.Encoder encoder = Base64.getEncoder().withoutPadding();
b.append(encoder.encodeToString(longToBytes(lastModified() ^ lhash)));
b.append(encoder.encodeToString(longToBytes(length() ^ lhash)));
b.append(suffix);
b.append('"');
return b.toString();
}
catch (IOException e)
private static byte[] longToBytes(long value)
{
throw new RuntimeException(e);
byte[] result = new byte[Long.BYTES];
for (int i = Long.BYTES - 1; i >= 0; i--)
{
result[i] = (byte) (value & 0xFF);
value >>= 8;
}
return result;
}
/* ------------------------------------------------------------ */

View File

@ -18,70 +18,120 @@
package org.eclipse.jetty.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
public class B64CodeTest
{
String text = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.";
String text = "Man is distinguished, not only by his reason, but by this singular passion " +
"from other animals, which is a lust of the mind, that by a perseverance of delight in " +
"the continued and indefatigable generation of knowledge, exceeds the short vehemence " +
"of any carnal pleasure.";
@Test
public void testRFC1421() throws Exception
public void testEncode_RFC1421()
{
String b64 = B64Code.encode(text, StandardCharsets.ISO_8859_1);
assertEquals("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"+
String expected = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz" +
"IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg" +
"dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu" +
"dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo" +
"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=",b64);
"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=";
char[] chars = B64Code.encode(text.getBytes(StandardCharsets.ISO_8859_1),false);
// Default Encode
String b64 = B64Code.encode(text, ISO_8859_1);
assertThat("B64Code.encode(String)", b64, is(expected));
// Specified RFC Encode
byte[] rawInputBytes = text.getBytes(ISO_8859_1);
char[] chars = B64Code.encode(rawInputBytes,false);
b64 = new String(chars,0,chars.length);
assertEquals("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"+
"IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg"+
"dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu"+
"dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo"+
"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=",b64);
assertThat("B64Code.encode(byte[], false)", b64, is(expected));
// Standard Java Encode
String javaBase64 = Base64.getEncoder().encodeToString(rawInputBytes);
assertThat("Base64.getEncoder().encodeToString((byte[])", javaBase64, is(expected));
}
@Test
public void testRFC2045() throws Exception
public void testEncode_RFC2045()
{
char[] chars = B64Code.encode(text.getBytes(StandardCharsets.ISO_8859_1),true);
byte[] rawInputBytes = text.getBytes(ISO_8859_1);
// Old Jetty way
char[] chars = B64Code.encode(rawInputBytes,true);
String b64 = new String(chars,0,chars.length);
assertEquals("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz\r\n"+
String expected = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz\r\n"+
"IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg\r\n"+
"dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu\r\n"+
"dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo\r\n"+
"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=\r\n",b64);
"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=\r\n";
assertThat(b64, is(expected));
// Standard Java way
String javaBase64 = Base64.getMimeEncoder().encodeToString(rawInputBytes);
assertThat(javaBase64, is(expected));
}
@Test
public void testInteger() throws Exception
{
byte[] bytes = text.getBytes(StandardCharsets.ISO_8859_1);
int value=(bytes[0]<<24)+(bytes[1]<<16)+(bytes[2]<<8)+(bytes[3]);
byte[] bytes = text.getBytes(ISO_8859_1);
int value = (bytes[0] << 24) +
(bytes[1] << 16) +
(bytes[2] << 8) +
(bytes[3]);
String expected = "TWFuIA";
// Old Jetty way
StringBuilder b = new StringBuilder();
B64Code.encode(value,b);
assertEquals("TWFuIA=",b.toString());
assertThat("Old Jetty B64Code", b.toString(), is(expected));
// Standard Java technique
byte[] intBytes = new byte[Integer.BYTES];
for (int i = Integer.BYTES - 1; i >= 0; i--)
{
intBytes[i] = (byte) (value & 0xFF);
value >>= 8;
}
assertThat("Standard Java Base64", Base64.getEncoder().withoutPadding().encodeToString(intBytes), is(expected));
}
@Test
public void testLong() throws Exception
{
byte[] bytes = text.getBytes(StandardCharsets.ISO_8859_1);
long value=((0xffL&bytes[0])<<56)+((0xffL&bytes[1])<<48)+((0xffL&bytes[2])<<40)+((0xffL&bytes[3])<<32)+
((0xffL&bytes[4])<<24)+((0xffL&bytes[5])<<16)+((0xffL&bytes[6])<<8)+(0xffL&bytes[7]);
byte[] bytes = text.getBytes(ISO_8859_1);
long value = ((0xffL & bytes[0]) << 56) +
((0xffL & bytes[1]) << 48) +
((0xffL & bytes[2]) << 40) +
((0xffL & bytes[3]) << 32) +
((0xffL & bytes[4]) << 24) +
((0xffL & bytes[5]) << 16) +
((0xffL & bytes[6]) << 8) +
(0xffL & bytes[7]);
String expected = "TWFuIGlzIGQ";
// Old Jetty way
StringBuilder b = new StringBuilder();
B64Code.encode(value,b);
assertEquals("TWFuIGlzIGQ",b.toString());
assertThat("Old Jetty B64Code", b.toString(), is(expected));
// Standard Java technique
byte[] longBytes = new byte[Long.BYTES];
for (int i = Long.BYTES - 1; i >= 0; i--)
{
longBytes[i] = (byte) (value & 0xFF);
value >>= 8;
}
assertThat("Standard Java Base64", Base64.getEncoder().withoutPadding().encodeToString(longBytes), is(expected));
}
}

View File

@ -18,6 +18,26 @@
package org.eclipse.jetty.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.Collection;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Part;
import org.eclipse.jetty.util.MultiPartInputStreamParser.MultiPart;
import org.eclipse.jetty.util.MultiPartInputStreamParser.NonCompliance;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
@ -31,25 +51,6 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Part;
import org.eclipse.jetty.util.MultiPartInputStreamParser.MultiPart;
import org.eclipse.jetty.util.MultiPartInputStreamParser.NonCompliance;
import org.junit.jupiter.api.Test;
/**
* MultiPartInputStreamTest
*
@ -996,7 +997,7 @@ public class MultiPartInputStreamTest
"Content-Transfer-Encoding: base64\r\n"+
"Content-Type: application/octet-stream\r\n"+
"\r\n"+
B64Code.encode("hello jetty") + "\r\n"+
Base64.getEncoder().encodeToString("hello jetty".getBytes(ISO_8859_1)) + "\r\n"+
"--AaB03x\r\n"+
"Content-disposition: form-data; name=\"final\"\r\n"+
"Content-Type: text/plain\r\n"+

View File

@ -23,14 +23,13 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@ -38,6 +37,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.startsWith;
@ -93,7 +93,7 @@ public class WebSocketNegotiationTest
httpFields.remove(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL);
httpFields.add(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "testInvalidUpgradeRequest");
String upgradeRequest = "GET / HTTP/1.1\r\n" + httpFields;
client.getOutputStream().write(upgradeRequest.getBytes(StandardCharsets.ISO_8859_1));
client.getOutputStream().write(upgradeRequest.getBytes(ISO_8859_1));
String response = getUpgradeResponse(client.getInputStream());
assertThat(response, startsWith("HTTP/1.1 101 Switching Protocols"));
@ -112,7 +112,7 @@ public class WebSocketNegotiationTest
httpFields.remove(HttpHeader.SEC_WEBSOCKET_KEY);
String upgradeRequest = "GET / HTTP/1.1\r\n" + httpFields;
client.getOutputStream().write(upgradeRequest.getBytes(StandardCharsets.ISO_8859_1));
client.getOutputStream().write(upgradeRequest.getBytes(ISO_8859_1));
String response = getUpgradeResponse(client.getInputStream());
assertThat(response, containsString("400 Missing request header 'Sec-WebSocket-Key'"));
@ -125,7 +125,7 @@ public class WebSocketNegotiationTest
fields.add(HttpHeader.HOST, "127.0.0.1");
fields.add(HttpHeader.UPGRADE, "websocket");
fields.add(HttpHeader.CONNECTION, "Upgrade");
fields.add(HttpHeader.SEC_WEBSOCKET_KEY, new String(B64Code.encode("0123456701234567".getBytes())));
fields.add(HttpHeader.SEC_WEBSOCKET_KEY, Base64.getEncoder().encodeToString("0123456701234567".getBytes(ISO_8859_1)));
fields.add(HttpHeader.SEC_WEBSOCKET_VERSION, "13");
fields.add(HttpHeader.PRAGMA, "no-cache");
fields.add(HttpHeader.CACHE_CONTROL, "no-cache");

View File

@ -23,6 +23,7 @@ import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -33,7 +34,6 @@ import java.util.concurrent.ThreadLocalRandom;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.UrlEncoded;
@ -126,7 +126,7 @@ public class ClientUpgradeRequest extends UpgradeRequestAdapter
{
byte[] bytes = new byte[16];
ThreadLocalRandom.current().nextBytes(bytes);
return new String(B64Code.encode(bytes));
return Base64.getEncoder().encodeToString(bytes);
}
public String getKey()

View File

@ -24,6 +24,7 @@ import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -52,7 +53,6 @@ import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.UrlEncoded;
@ -425,7 +425,7 @@ public class WebSocketUpgradeRequest extends HttpRequest implements CompleteList
{
byte[] bytes = new byte[16];
ThreadLocalRandom.current().nextBytes(bytes);
return new String(B64Code.encode(bytes));
return Base64.getEncoder().encodeToString(bytes);
}
private ExtensionFactory getExtensionFactory()

View File

@ -20,8 +20,7 @@ package org.eclipse.jetty.websocket.common;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import org.eclipse.jetty.util.B64Code;
import java.util.Base64;
/**
* Logic for working with the <code>Sec-WebSocket-Key</code> and <code>Sec-WebSocket-Accept</code> headers.
@ -51,7 +50,7 @@ public class AcceptHash
MessageDigest md = MessageDigest.getInstance("SHA1");
md.update(key.getBytes(StandardCharsets.UTF_8));
md.update(MAGIC);
return new String(B64Code.encode(md.digest()));
return Base64.getEncoder().encodeToString(md.digest());
}
catch (Exception e)
{

View File

@ -18,14 +18,14 @@
package org.eclipse.jetty.websocket.common;
import java.util.Base64;
import org.eclipse.jetty.util.TypeUtil;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.TypeUtil;
import org.junit.jupiter.api.Test;
public class AcceptHashTest
{
@Test
@ -35,7 +35,7 @@ public class AcceptHashTest
assertThat("Key size",key.length,is(16));
// what the client sends
String clientKey = String.valueOf(B64Code.encode(key));
String clientKey = Base64.getEncoder().encodeToString(key);
// what the server responds with
String serverHash = AcceptHash.hashKey(clientKey);

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.websocket.common.test;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@ -44,7 +45,6 @@ import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -76,7 +76,7 @@ public class BlockheadClientRequest extends HttpRequest implements Response.Comp
{
byte[] bytes = new byte[16];
ThreadLocalRandom.current().nextBytes(bytes);
return new String(B64Code.encode(bytes));
return Base64.getEncoder().encodeToString(bytes);
}
private void initWebSocketHeaders()

View File

@ -24,6 +24,7 @@ import java.io.OutputStream;
import java.net.Socket;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.server.Server;
@ -32,7 +33,6 @@ import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.websocket.server.helper.EchoSocket;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@ -103,12 +103,13 @@ public class WebSocketProtocolTest
{
byte[] key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
StringBuilder request = new StringBuilder();
String secWebSocketKey = Base64.getEncoder().encodeToString(key);
request.append("GET /ws HTTP/1.1\r\n")
.append("Host: localhost\r\n")
.append("Connection: Upgrade\r\n")
.append("Upgrade: websocket\r\n")
.append("Sec-WebSocket-version: 13\r\n")
.append("Sec-WebSocket-Key:").append(B64Code.encode(key)).append("\r\n")
.append("Sec-WebSocket-Key:").append(secWebSocketKey).append("\r\n")
.append("Sec-WebSocket-Protocol: echo\r\n")
.append("\r\n");