Java源码示例:io.undertow.util.FlexBase64
示例1
private static byte[] base64Decode(String sessionId) {
try {
ByteBuf sessionIdBuffer = FlexBase64.decode(sessionId);
byte[] sessionIdData;
if (sessionIdBuffer.hasArray()) {
sessionIdData = sessionIdBuffer.array();
} else {
sessionIdData = new byte[sessionIdBuffer.readableBytes()];
sessionIdBuffer.readBytes(sessionIdData);
}
return sessionIdData;
} catch (IOException e) {
//can happen if the session id is invalid
return null;
}
}
示例2
private static byte[] base64Decode(String sessionId) {
try {
ByteBuffer sessionIdBuffer = FlexBase64.decode(sessionId);
byte[] sessionIdData;
if (sessionIdBuffer.hasArray()) {
sessionIdData = sessionIdBuffer.array();
} else {
sessionIdData = new byte[sessionIdBuffer.remaining()];
sessionIdBuffer.get(sessionIdData);
}
return sessionIdData;
} catch (IOException e) {
//can happen if the session id is invalid
return null;
}
}
示例3
@Test
public void testAuthenticatedWebsocket() throws Exception {
ProgramaticClientEndpoint endpoint = new ProgramaticClientEndpoint();
ClientEndpointConfig clientEndpointConfig = ClientEndpointConfig.Builder.create().configurator(new ClientConfigurator(){
@Override
public void beforeRequest(Map<String, List<String>> headers) {
headers.put(AUTHORIZATION.toString(), Collections.singletonList(BASIC + " " + FlexBase64.encodeString("user1:password1".getBytes(), false)));
}
}).build();
ContainerProvider.getWebSocketContainer().connectToServer(endpoint, clientEndpointConfig, new URI("ws://" + DefaultServer.getHostAddress("default") + ":" + DefaultServer.getHostPort("default") + "/servletContext/secured"));
Assert.assertEquals("user1", endpoint.getResponses().poll(15, TimeUnit.SECONDS));
endpoint.session.close();
endpoint.closeLatch.await(10, TimeUnit.SECONDS);
}
示例4
private static String md5(byte[] buffer) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(buffer);
byte[] digest = md.digest();
return new String(FlexBase64.encodeBytes(digest, 0, digest.length, false));
} catch (NoSuchAlgorithmException e) {
// Should never happen
throw new InternalError("MD5 not supported on this platform");
}
}
示例5
public ChallengeResult sendChallenge(final HttpServerExchange exchange, final SecurityContext securityContext) {
NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);
String header = NEGOTIATION_PLAIN;
if (negContext != null) {
byte[] responseChallenge = negContext.useResponseToken();
exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, null);
if (responseChallenge != null) {
header = NEGOTIATE_PREFIX + FlexBase64.encodeString(responseChallenge, false);
}
} else {
Subject server = null;
try {
server = subjectFactory.getSubjectForHost(getHostName(exchange));
} catch (GeneralSecurityException e) {
// Deliberately ignore - no Subject so don't offer GSSAPI is our main concern here.
}
if (server == null) {
return ChallengeResult.NOT_SENT;
}
}
exchange.addResponseHeader(WWW_AUTHENTICATE, header);
UndertowLogger.SECURITY_LOGGER.debugf("Sending GSSAPI challenge for %s", exchange);
return new ChallengeResult(true, UNAUTHORIZED);
}
示例6
public SimpleNonceManager(final String hashAlg) {
// Verify it is a valid algorithm (at least for now)
MessageDigest digest = getDigest(hashAlg);
this.hashAlg = hashAlg;
this.hashLength = digest.getDigestLength();
// Create a new secret only valid within this NonceManager instance.
Random rand = new SecureRandom();
byte[] secretBytes = new byte[32];
rand.nextBytes(secretBytes);
secret = FlexBase64.encodeString(digest.digest(secretBytes), false);
}
示例7
private String createNonce(final byte[] prefix, final byte[] timeStamp) {
byte[] hashedPart = generateHash(prefix, timeStamp);
byte[] complete = new byte[9 + timeStamp.length + hashedPart.length];
System.arraycopy(prefix, 0, complete, 0, 8);
complete[8] = (byte) timeStamp.length;
System.arraycopy(timeStamp, 0, complete, 9, timeStamp.length);
System.arraycopy(hashedPart, 0, complete, 9 + timeStamp.length, hashedPart.length);
return FlexBase64.encodeString(complete, false);
}
示例8
@Override
public String readAttribute(HttpServerExchange exchange) {
SSLSessionInfo ssl = exchange.getSslSessionInfo();
if(ssl == null || ssl.getSessionId() == null) {
return null;
}
return FlexBase64.encodeString(ssl.getSessionId(), false);
}
示例9
/**
* Generate the MD5 hash out of the given {@link ByteBuffer}
*/
private static String md5(byte[] buffer) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(buffer);
byte[] digest = md.digest();
return new String(FlexBase64.encodeBytes(digest, 0, digest.length, false), StandardCharsets.US_ASCII);
} catch (NoSuchAlgorithmException e) {
// Should never happen
throw new InternalError("MD5 not supported on this platform");
}
}
示例10
public ChallengeResult sendChallenge(final HttpServerExchange exchange, final SecurityContext securityContext) {
NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);
String header = NEGOTIATION_PLAIN;
if (negContext != null) {
byte[] responseChallenge = negContext.useResponseToken();
exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, null);
if (responseChallenge != null) {
header = NEGOTIATE_PREFIX + FlexBase64.encodeString(responseChallenge, false);
}
} else {
Subject server = null;
try {
server = subjectFactory.getSubjectForHost(getHostName(exchange));
} catch (GeneralSecurityException e) {
// Deliberately ignore - no Subject so don't offer GSSAPI is our main concern here.
}
if (server == null) {
return ChallengeResult.NOT_SENT;
}
}
exchange.getResponseHeaders().add(WWW_AUTHENTICATE, header);
UndertowLogger.SECURITY_LOGGER.debugf("Sending GSSAPI challenge for %s", exchange);
return new ChallengeResult(true, UNAUTHORIZED);
}
示例11
public SimpleNonceManager(final String hashAlg) {
// Verify it is a valid algorithm (at least for now)
MessageDigest digest = getDigest(hashAlg);
this.hashAlg = hashAlg;
this.hashLength = digest.getDigestLength();
// Create a new secret only valid within this NonceManager instance.
Random rand = new SecureRandom();
byte[] secretBytes = new byte[32];
rand.nextBytes(secretBytes);
secret = FlexBase64.encodeString(digest.digest(secretBytes), false);
}
示例12
private String createNonce(final byte[] prefix, final byte[] timeStamp) {
byte[] hashedPart = generateHash(prefix, timeStamp);
byte[] complete = new byte[9 + timeStamp.length + hashedPart.length];
System.arraycopy(prefix, 0, complete, 0, 8);
complete[8] = (byte) timeStamp.length;
System.arraycopy(timeStamp, 0, complete, 9, timeStamp.length);
System.arraycopy(hashedPart, 0, complete, 9 + timeStamp.length, hashedPart.length);
return FlexBase64.encodeString(complete, false);
}
示例13
@Override
public String readAttribute(HttpServerExchange exchange) {
SSLSessionInfo ssl = exchange.getConnection().getSslSessionInfo();
if(ssl == null || ssl.getSessionId() == null) {
return null;
}
return FlexBase64.encodeString(ssl.getSessionId(), false);
}
示例14
public static String createSettingsFrame(OptionMap options, ByteBufferPool bufferPool) {
PooledByteBuffer b = bufferPool.allocate();
try {
ByteBuffer currentBuffer = b.getBuffer();
if (options.contains(UndertowOptions.HTTP2_SETTINGS_HEADER_TABLE_SIZE)) {
pushOption(currentBuffer, Http2Setting.SETTINGS_HEADER_TABLE_SIZE, options.get(UndertowOptions.HTTP2_SETTINGS_HEADER_TABLE_SIZE));
}
if (options.contains(UndertowOptions.HTTP2_SETTINGS_ENABLE_PUSH)) {
pushOption(currentBuffer, Http2Setting.SETTINGS_ENABLE_PUSH, options.get(UndertowOptions.HTTP2_SETTINGS_ENABLE_PUSH) ? 1 : 0);
}
if (options.contains(UndertowOptions.HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)) {
pushOption(currentBuffer, Http2Setting.SETTINGS_MAX_CONCURRENT_STREAMS, options.get(UndertowOptions.HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
}
if (options.contains(UndertowOptions.HTTP2_SETTINGS_INITIAL_WINDOW_SIZE)) {
pushOption(currentBuffer, Http2Setting.SETTINGS_INITIAL_WINDOW_SIZE, options.get(UndertowOptions.HTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
}
if (options.contains(UndertowOptions.HTTP2_SETTINGS_MAX_FRAME_SIZE)) {
pushOption(currentBuffer, Http2Setting.SETTINGS_MAX_FRAME_SIZE, options.get(UndertowOptions.HTTP2_SETTINGS_MAX_FRAME_SIZE));
}
if (options.contains(UndertowOptions.HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE)) {
pushOption(currentBuffer, Http2Setting.SETTINGS_MAX_HEADER_LIST_SIZE, options.get(UndertowOptions.HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE));
} else if(options.contains(UndertowOptions.MAX_HEADER_SIZE)) {
pushOption(currentBuffer, Http2Setting.SETTINGS_MAX_HEADER_LIST_SIZE, options.get(UndertowOptions.HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE));
}
currentBuffer.flip();
return FlexBase64.encodeStringURL(currentBuffer, false);
} finally {
b.close();
}
}
示例15
/**
* Generate the MD5 hash out of the given {@link ByteBuffer}
*/
private static String md5(byte[] buffer) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(buffer);
byte[] digest = md.digest();
return new String(FlexBase64.encodeBytes(digest, 0, digest.length, false), StandardCharsets.US_ASCII);
} catch (NoSuchAlgorithmException e) {
// Should never happen
throw new InternalError("MD5 not supported on this platform");
}
}
示例16
protected String createSecKey() {
SecureRandom random = new SecureRandom();
byte[] data = new byte[16];
for (int i = 0; i < 4; ++i) {
int val = random.nextInt();
data[i * 4] = (byte) val;
data[i * 4 + 1] = (byte) ((val >> 8) & 0xFF);
data[i * 4 + 2] = (byte) ((val >> 16) & 0xFF);
data[i * 4 + 3] = (byte) ((val >> 24) & 0xFF);
}
return FlexBase64.encodeString(data, false);
}
示例17
protected final String solve(final String nonceBase64) {
try {
final String concat = nonceBase64 + MAGIC_NUMBER;
final MessageDigest digest = MessageDigest.getInstance("SHA1");
digest.update(concat.getBytes(StandardCharsets.UTF_8));
final byte[] bytes = digest.digest();
return FlexBase64.encodeString(bytes, false);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
示例18
@Override
public ChallengeResult sendChallenge(final HttpServerExchange exchange, final SecurityContext securityContext) {
NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);
String header = NEGOTIATION_PLAIN;
if (negContext != null) {
byte[] responseChallenge = negContext.useResponseToken();
exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, null);
if (responseChallenge != null) {
header = NEGOTIATE_PREFIX + FlexBase64.encodeString(responseChallenge, false);
}
} else {
Subject server = null;
try {
server = subjectFactory.getSubjectForHost(getHostName(exchange));
} catch (GeneralSecurityException e) {
// Deliberately ignore - no Subject so don't offer GSSAPI is our main concern here.
}
if (server == null) {
return ChallengeResult.NOT_SENT;
}
}
exchange.getResponseHeaders().add(WWW_AUTHENTICATE, header);
if(logger.isDebugEnabled()) logger.debug("Sending GSSAPI challenge for %s", exchange);
return new ChallengeResult(true, UNAUTHORIZED);
}
示例19
@SuppressWarnings("unchecked")
private String authenticate(String authHeader) throws ApiException {
String result = null;
if (authHeader.toLowerCase(Locale.ENGLISH).startsWith(LOWERCASE_BASIC_PREFIX)) {
String base64Challenge = authHeader.substring(PREFIX_LENGTH);
String plainChallenge;
try {
ByteBuffer decode = FlexBase64.decode(base64Challenge);
// assume charset is UTF_8
Charset charset = StandardCharsets.UTF_8;
plainChallenge = new String(decode.array(), decode.arrayOffset(), decode.limit(), charset);
logger.debug("Found basic auth header %s (decoded using charset %s) in %s", plainChallenge, charset, authHeader);
int colonPos;
if ((colonPos = plainChallenge.indexOf(COLON)) > -1) {
String clientId = plainChallenge.substring(0, colonPos);
String clientSecret = plainChallenge.substring(colonPos + 1);
// match with db/cached user credentials.
IMap<String, Client> clients = CacheStartupHookProvider.hz.getMap("clients");
Client client = clients.get(clientId);
if(client == null) {
throw new ApiException(new Status(CLIENT_NOT_FOUND, clientId));
}
if(!HashUtil.validatePassword(clientSecret.toCharArray(), client.getClientSecret())) {
throw new ApiException(new Status(UNAUTHORIZED_CLIENT));
}
result = clientId;
}
} catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
logger.error("Exception:", e);
throw new ApiException(new Status(RUNTIME_EXCEPTION));
}
}
return result;
}
示例20
@Override
public AuthenticationMechanismOutcome authenticate(final HttpServerExchange exchange,
final SecurityContext securityContext) {
NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);
if (negContext != null) {
UndertowLogger.SECURITY_LOGGER.debugf("Existing negotiation context found for %s", exchange);
exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
if (negContext.isEstablished()) {
IdentityManager identityManager = getIdentityManager(securityContext);
final Account account = identityManager.verify(new GSSContextCredential(negContext.getGssContext()));
if (account != null) {
securityContext.authenticationComplete(account, name, false);
UndertowLogger.SECURITY_LOGGER.debugf("Authenticated as user %s with existing GSSAPI negotiation context for %s", account.getPrincipal().getName(), exchange);
return AuthenticationMechanismOutcome.AUTHENTICATED;
} else {
UndertowLogger.SECURITY_LOGGER.debugf("Failed to authenticate with existing GSSAPI negotiation context for %s", exchange);
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
}
List<String> authHeaders = exchange.getRequestHeaders(AUTHORIZATION);
if (authHeaders != null) {
for (String current : authHeaders) {
if (current.startsWith(NEGOTIATE_PREFIX)) {
String base64Challenge = current.substring(NEGOTIATE_PREFIX.length());
try {
ByteBuf challenge = FlexBase64.decode(base64Challenge);
return runGSSAPI(exchange, challenge, securityContext);
} catch (IOException e) {
}
// By this point we had a header we should have been able to verify but for some reason
// it was not correctly structured.
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
}
// No suitable header was found so authentication was not even attempted.
return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
示例21
public AuthenticationMechanismOutcome run() throws GSSException {
NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);
if (negContext == null) {
negContext = new NegotiationContext();
exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
}
GSSContext gssContext = negContext.getGssContext();
if (gssContext == null) {
GSSManager manager = GSSManager.getInstance();
GSSCredential credential = manager.createCredential(null, GSSCredential.INDEFINITE_LIFETIME, mechanisms, GSSCredential.ACCEPT_ONLY);
gssContext = manager.createContext(credential);
negContext.setGssContext(gssContext);
}
byte[] respToken = gssContext.acceptSecContext(challenge.array(), challenge.arrayOffset(), challenge.writerIndex());
negContext.setResponseToken(respToken);
if (negContext.isEstablished()) {
if (respToken != null) {
// There will be no further challenge but we do have a token so set it here.
exchange.addResponseHeader(WWW_AUTHENTICATE,
NEGOTIATE_PREFIX + FlexBase64.encodeString(respToken, false));
}
IdentityManager identityManager = securityContext.getIdentityManager();
final Account account = identityManager.verify(new GSSContextCredential(negContext.getGssContext()));
if (account != null) {
securityContext.authenticationComplete(account, name, false);
return AuthenticationMechanismOutcome.AUTHENTICATED;
} else {
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
} else {
// This isn't a failure but as the context is not established another round trip with the client is needed.
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
示例22
/**
* Verify a previously unknown nonce and return the {@link NonceKey} representation for the nonce.
* <p>
* Later when a nonce is re-used we can match based on the String alone - the information embedded within the nonce will be
* cached with it.
* <p>
* This stage of the verification simply extracts the prefix and the embedded timestamp and recreates a new hashed and
* Base64 nonce based on the local secret - if the newly generated nonce matches the supplied one we accept it was created
* by this nonce manager.
* <p>
* This verification does not validate that the timestamp is within a valid time period.
*
* @param nonce -
* @return
*/
private Nonce verifyUnknownNonce(final String nonce, final int nonceCount) {
byte[] complete;
int offset;
int length;
try {
ByteBuf decode = FlexBase64.decode(nonce);
complete = decode.array();
offset = decode.arrayOffset();
length = decode.writerIndex() - offset;
} catch (IOException e) {
throw MESSAGES.invalidBase64Token(e);
}
int timeStampLength = complete[offset + 8];
// A sanity check to try and verify the sizes we expect from the arrays are correct.
if (hashLength > 0) {
int expectedLength = 9 + timeStampLength + hashLength;
if (length != expectedLength) {
throw MESSAGES.invalidNonceReceived();
} else if (timeStampLength + 1 >= length)
throw MESSAGES.invalidNonceReceived();
}
byte[] prefix = new byte[8];
System.arraycopy(complete, offset, prefix, 0, 8);
byte[] timeStampBytes = new byte[timeStampLength];
System.arraycopy(complete, offset + 9, timeStampBytes, 0, timeStampBytes.length);
String expectedNonce = createNonce(prefix, timeStampBytes);
if (expectedNonce.equals(nonce)) {
try {
long timeStamp = Long.parseLong(new String(timeStampBytes, StandardCharsets.UTF_8));
return new Nonce(expectedNonce, timeStamp, nonceCount);
} catch (NumberFormatException dropped) {
}
}
return null;
}
示例23
/**
* @see io.undertow.server.HttpHandler#handleRequest(io.undertow.server.HttpServerExchange)
*/
@Override
public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
List<String> authHeaders = exchange.getRequestHeaders(AUTHORIZATION);
if (authHeaders != null) {
for (String current : authHeaders) {
if (current.toLowerCase(Locale.ENGLISH).startsWith(LOWERCASE_BASIC_PREFIX)) {
String base64Challenge = current.substring(PREFIX_LENGTH);
String plainChallenge = null;
try {
ByteBuf decode = FlexBase64.decode(base64Challenge);
Charset charset = this.charset;
if(!userAgentCharsets.isEmpty()) {
String ua = exchange.getRequestHeader(HttpHeaderNames.USER_AGENT);
if(ua != null) {
for (Map.Entry<Pattern, Charset> entry : userAgentCharsets.entrySet()) {
if(entry.getKey().matcher(ua).find()) {
charset = entry.getValue();
break;
}
}
}
}
plainChallenge = new String(decode.array(), decode.arrayOffset(), decode.writerIndex(), charset);
UndertowLogger.SECURITY_LOGGER.debugf("Found basic auth header %s (decoded using charset %s) in %s", plainChallenge, charset, exchange);
} catch (IOException e) {
UndertowLogger.SECURITY_LOGGER.debugf(e, "Failed to decode basic auth header %s in %s", base64Challenge, exchange);
}
int colonPos;
if (plainChallenge != null && (colonPos = plainChallenge.indexOf(COLON)) > -1) {
String userName = plainChallenge.substring(0, colonPos);
char[] password = plainChallenge.substring(colonPos + 1).toCharArray();
IdentityManager idm = getIdentityManager(securityContext);
PasswordCredential credential = new PasswordCredential(password);
try {
final AuthenticationMechanismOutcome result;
Account account = idm.verify(userName, credential);
if (account != null) {
securityContext.authenticationComplete(account, name, false);
result = AuthenticationMechanismOutcome.AUTHENTICATED;
} else {
securityContext.authenticationFailed(MESSAGES.authenticationFailed(userName), name);
result = AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
return result;
} finally {
clear(password);
}
}
// By this point we had a header we should have been able to verify but for some reason
// it was not correctly structured.
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
}
// No suitable header has been found in this request,
return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
示例24
@Override
public AuthenticationMechanismOutcome authenticate(final HttpServerExchange exchange,
final SecurityContext securityContext) {
ServerConnection connection = exchange.getConnection();
NegotiationContext negContext = connection.getAttachment(NegotiationContext.ATTACHMENT_KEY);
if (negContext != null) {
UndertowLogger.SECURITY_LOGGER.debugf("Existing negotiation context found for %s", exchange);
exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
if (negContext.isEstablished()) {
IdentityManager identityManager = getIdentityManager(securityContext);
final Account account = identityManager.verify(new GSSContextCredential(negContext.getGssContext()));
if (account != null) {
securityContext.authenticationComplete(account, name, false);
UndertowLogger.SECURITY_LOGGER.debugf("Authenticated as user %s with existing GSSAPI negotiation context for %s", account.getPrincipal().getName(), exchange);
return AuthenticationMechanismOutcome.AUTHENTICATED;
} else {
UndertowLogger.SECURITY_LOGGER.debugf("Failed to authenticate with existing GSSAPI negotiation context for %s", exchange);
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
}
List<String> authHeaders = exchange.getRequestHeaders().get(AUTHORIZATION);
if (authHeaders != null) {
for (String current : authHeaders) {
if (current.startsWith(NEGOTIATE_PREFIX)) {
String base64Challenge = current.substring(NEGOTIATE_PREFIX.length());
try {
ByteBuffer challenge = FlexBase64.decode(base64Challenge);
return runGSSAPI(exchange, challenge, securityContext);
} catch (IOException e) {
}
// By this point we had a header we should have been able to verify but for some reason
// it was not correctly structured.
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
}
// No suitable header was found so authentication was not even attempted.
return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
示例25
public AuthenticationMechanismOutcome run() throws GSSException {
NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);
if (negContext == null) {
negContext = new NegotiationContext();
exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
// Also cache it on the connection for future calls.
exchange.getConnection().putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
}
GSSContext gssContext = negContext.getGssContext();
if (gssContext == null) {
GSSManager manager = GSSManager.getInstance();
GSSCredential credential = manager.createCredential(null, GSSCredential.INDEFINITE_LIFETIME, mechanisms, GSSCredential.ACCEPT_ONLY);
gssContext = manager.createContext(credential);
negContext.setGssContext(gssContext);
}
byte[] respToken = gssContext.acceptSecContext(challenge.array(), challenge.arrayOffset(), challenge.limit());
negContext.setResponseToken(respToken);
if (negContext.isEstablished()) {
if (respToken != null) {
// There will be no further challenge but we do have a token so set it here.
exchange.getResponseHeaders().add(WWW_AUTHENTICATE,
NEGOTIATE_PREFIX + FlexBase64.encodeString(respToken, false));
}
IdentityManager identityManager = securityContext.getIdentityManager();
final Account account = identityManager.verify(new GSSContextCredential(negContext.getGssContext()));
if (account != null) {
securityContext.authenticationComplete(account, name, false);
return AuthenticationMechanismOutcome.AUTHENTICATED;
} else {
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
} else {
// This isn't a failure but as the context is not established another round trip with the client is needed.
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
示例26
/**
* Verify a previously unknown nonce and return the {@link NonceKey} representation for the nonce.
*
* Later when a nonce is re-used we can match based on the String alone - the information embedded within the nonce will be
* cached with it.
*
* This stage of the verification simply extracts the prefix and the embedded timestamp and recreates a new hashed and
* Base64 nonce based on the local secret - if the newly generated nonce matches the supplied one we accept it was created
* by this nonce manager.
*
* This verification does not validate that the timestamp is within a valid time period.
*
* @param nonce -
* @return
*/
private Nonce verifyUnknownNonce(final String nonce, final int nonceCount) {
byte[] complete;
int offset;
int length;
try {
ByteBuffer decode = FlexBase64.decode(nonce);
complete = decode.array();
offset = decode.arrayOffset();
length = decode.limit() - offset;
} catch (IOException e) {
throw MESSAGES.invalidBase64Token(e);
}
int timeStampLength = complete[offset + 8];
// A sanity check to try and verify the sizes we expect from the arrays are correct.
if (hashLength > 0) {
int expectedLength = 9 + timeStampLength + hashLength;
if (length != expectedLength) {
throw MESSAGES.invalidNonceReceived();
} else if (timeStampLength + 1 >= length)
throw MESSAGES.invalidNonceReceived();
}
byte[] prefix = new byte[8];
System.arraycopy(complete, offset, prefix, 0, 8);
byte[] timeStampBytes = new byte[timeStampLength];
System.arraycopy(complete, offset + 9, timeStampBytes, 0, timeStampBytes.length);
String expectedNonce = createNonce(prefix, timeStampBytes);
if (expectedNonce.equals(nonce)) {
try {
long timeStamp = Long.parseLong(new String(timeStampBytes, StandardCharsets.UTF_8));
return new Nonce(expectedNonce, timeStamp, nonceCount);
} catch (NumberFormatException dropped) {
}
}
return null;
}
示例27
/**
* @see io.undertow.server.HttpHandler#handleRequest(io.undertow.server.HttpServerExchange)
*/
@Override
public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
List<String> authHeaders = exchange.getRequestHeaders().get(AUTHORIZATION);
if (authHeaders != null) {
for (String current : authHeaders) {
if (current.toLowerCase(Locale.ENGLISH).startsWith(LOWERCASE_BASIC_PREFIX)) {
String base64Challenge = current.substring(PREFIX_LENGTH);
String plainChallenge = null;
try {
ByteBuffer decode = FlexBase64.decode(base64Challenge);
Charset charset = this.charset;
if(!userAgentCharsets.isEmpty()) {
String ua = exchange.getRequestHeaders().getFirst(Headers.USER_AGENT);
if(ua != null) {
for (Map.Entry<Pattern, Charset> entry : userAgentCharsets.entrySet()) {
if(entry.getKey().matcher(ua).find()) {
charset = entry.getValue();
break;
}
}
}
}
plainChallenge = new String(decode.array(), decode.arrayOffset(), decode.limit(), charset);
UndertowLogger.SECURITY_LOGGER.debugf("Found basic auth header %s (decoded using charset %s) in %s", plainChallenge, charset, exchange);
} catch (IOException e) {
UndertowLogger.SECURITY_LOGGER.debugf(e, "Failed to decode basic auth header %s in %s", base64Challenge, exchange);
}
int colonPos;
if (plainChallenge != null && (colonPos = plainChallenge.indexOf(COLON)) > -1) {
String userName = plainChallenge.substring(0, colonPos);
char[] password = plainChallenge.substring(colonPos + 1).toCharArray();
IdentityManager idm = getIdentityManager(securityContext);
PasswordCredential credential = new PasswordCredential(password);
try {
final AuthenticationMechanismOutcome result;
Account account = idm.verify(userName, credential);
if (account != null) {
securityContext.authenticationComplete(account, name, false);
result = AuthenticationMechanismOutcome.AUTHENTICATED;
} else {
securityContext.authenticationFailed(MESSAGES.authenticationFailed(userName), name);
result = AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
return result;
} finally {
clear(password);
}
}
// By this point we had a header we should have been able to verify but for some reason
// it was not correctly structured.
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
}
// No suitable header has been found in this request,
return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
示例28
@Override
public AuthenticationMechanismOutcome authenticate(final HttpServerExchange exchange,
final SecurityContext securityContext) {
ServerConnection connection = exchange.getConnection();
NegotiationContext negContext = connection.getAttachment(NegotiationContext.ATTACHMENT_KEY);
if (negContext != null) {
if(logger.isDebugEnabled()) logger.debug("Existing negotiation context found for %s", exchange);
exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
if (negContext.isEstablished()) {
IdentityManager identityManager = getIdentityManager(securityContext);
// get the client authenticate class and user type from the exchange.
String clientAuthClass = null;
String userType = null;
Map<String, Deque<String>> params = exchange.getQueryParameters();
Deque<String> clientIdDeque = params.get("client_id");
if(clientIdDeque != null) {
String clientId = clientIdDeque.getFirst();
IMap<String, Client> clients = CacheStartupHookProvider.hz.getMap("clients");
Client client = clients.get(clientId);
if(client != null) {
clientAuthClass = client.getAuthenticateClass();
}
}
Deque<String> userTypeDeque = params.get("user_type");
if(userTypeDeque != null) {
userType = userTypeDeque.getFirst();
}
final Account account = identityManager.verify(new LightGSSContextCredential(negContext.getGssContext(), clientAuthClass, userType));
if (account != null) {
securityContext.authenticationComplete(account, name, false);
if(logger.isDebugEnabled()) logger.debug("Authenticated as user %s with existing GSSAPI negotiation context for %s", account.getPrincipal().getName(), exchange);
return AuthenticationMechanismOutcome.AUTHENTICATED;
} else {
if(logger.isDebugEnabled()) logger.debug("Failed to authenticate with existing GSSAPI negotiation context for %s", exchange);
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
}
List<String> authHeaders = exchange.getRequestHeaders().get(AUTHORIZATION);
if (authHeaders != null) {
for (String current : authHeaders) {
if (current.startsWith(NEGOTIATE_PREFIX)) {
String base64Challenge = current.substring(NEGOTIATE_PREFIX.length());
try {
ByteBuffer challenge = FlexBase64.decode(base64Challenge);
return runGSSAPI(exchange, challenge, securityContext);
} catch (IOException e) {
}
// By this point we had a header we should have been able to verify but for some reason
// it was not correctly structured.
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
}
// No suitable header was found so authentication was not even attempted.
return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
示例29
@Override
public AuthenticationMechanismOutcome run() throws GSSException {
NegotiationContext negContext = exchange.getAttachment(NegotiationContext.ATTACHMENT_KEY);
if (negContext == null) {
negContext = new NegotiationContext();
exchange.putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
// Also cache it on the connection for future calls.
exchange.getConnection().putAttachment(NegotiationContext.ATTACHMENT_KEY, negContext);
}
GSSContext gssContext = negContext.getGssContext();
if (gssContext == null) {
GSSManager manager = GSSManager.getInstance();
GSSCredential credential = manager.createCredential(null, GSSCredential.INDEFINITE_LIFETIME, mechanisms, GSSCredential.ACCEPT_ONLY);
gssContext = manager.createContext(credential);
negContext.setGssContext(gssContext);
}
byte[] respToken = gssContext.acceptSecContext(challenge.array(), challenge.arrayOffset(), challenge.limit());
negContext.setResponseToken(respToken);
if (negContext.isEstablished()) {
if (respToken != null) {
// There will be no further challenge but we do have a token so set it here.
exchange.getResponseHeaders().add(WWW_AUTHENTICATE,
NEGOTIATE_PREFIX + FlexBase64.encodeString(respToken, false));
}
IdentityManager identityManager = securityContext.getIdentityManager();
// get the client authenticate class and user type from the exchange.
String clientAuthClass = null;
String userType = null;
Map<String, Deque<String>> params = exchange.getQueryParameters();
Deque<String> clientIdDeque = params.get("client_id");
if(clientIdDeque != null) {
String clientId = clientIdDeque.getFirst();
IMap<String, Client> clients = CacheStartupHookProvider.hz.getMap("clients");
Client client = clients.get(clientId);
if(client != null) {
clientAuthClass = client.getAuthenticateClass();
}
}
Deque<String> userTypeDeque = params.get("user_type");
if(userTypeDeque != null) {
userType = userTypeDeque.getFirst();
}
final Account account = identityManager.verify(new LightGSSContextCredential(negContext.getGssContext(), clientAuthClass, userType));
if (account != null) {
securityContext.authenticationComplete(account, name, false);
return AuthenticationMechanismOutcome.AUTHENTICATED;
} else {
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
} else {
// This isn't a failure but as the context is not established another round trip with the client is needed.
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
示例30
/**
* @see io.undertow.server.HttpHandler#handleRequest(io.undertow.server.HttpServerExchange)
*/
@Override
public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
List<String> authHeaders = exchange.getRequestHeaders().get(AUTHORIZATION);
if (authHeaders != null) {
for (String current : authHeaders) {
if (current.toLowerCase(Locale.ENGLISH).startsWith(LOWERCASE_BASIC_PREFIX)) {
String base64Challenge = current.substring(PREFIX_LENGTH);
String plainChallenge = null;
try {
ByteBuffer decode = FlexBase64.decode(base64Challenge);
Charset charset = this.charset;
if(!userAgentCharsets.isEmpty()) {
String ua = exchange.getRequestHeaders().getFirst(Headers.USER_AGENT);
if(ua != null) {
for (Map.Entry<Pattern, Charset> entry : userAgentCharsets.entrySet()) {
if(entry.getKey().matcher(ua).find()) {
charset = entry.getValue();
break;
}
}
}
}
plainChallenge = new String(decode.array(), decode.arrayOffset(), decode.limit(), charset);
if(logger.isDebugEnabled()) logger.debug("Found basic auth header %s (decoded using charset %s) in %s", plainChallenge, charset, exchange);
} catch (IOException e) {
logger.error("Failed to decode basic auth header " + base64Challenge + " in " + exchange, e);
}
int colonPos;
if (plainChallenge != null && (colonPos = plainChallenge.indexOf(COLON)) > -1) {
String userName = plainChallenge.substring(0, colonPos);
char[] password = plainChallenge.substring(colonPos + 1).toCharArray();
// get clientAuthClass and userType
String clientAuthClass = null;
String userType = null;
Map<String, Deque<String>> params = exchange.getQueryParameters();
Deque<String> clientIdDeque = params.get("client_id");
if(clientIdDeque != null) {
String clientId = clientIdDeque.getFirst();
IMap<String, Client> clients = CacheStartupHookProvider.hz.getMap("clients");
Client client = clients.get(clientId);
if(client != null) {
clientAuthClass = client.getAuthenticateClass();
}
}
Deque<String> userTypeDeque = params.get("user_type");
if(userTypeDeque != null) {
userType = userTypeDeque.getFirst();
}
IdentityManager idm = getIdentityManager(securityContext);
LightPasswordCredential credential = new LightPasswordCredential(password, clientAuthClass, userType, exchange);
try {
final AuthenticationMechanismOutcome result;
Account account = idm.verify(userName, credential);
if (account != null) {
securityContext.authenticationComplete(account, name, false);
result = AuthenticationMechanismOutcome.AUTHENTICATED;
} else {
securityContext.authenticationFailed(MESSAGES.authenticationFailed(userName), name);
result = AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
return result;
} finally {
clear(password);
}
}
// By this point we had a header we should have been able to verify but for some reason
// it was not correctly structured.
return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
}
}
}
// No suitable header has been found in this request,
return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}