Upgrade Resteasy v4
Closes #10916 Co-authored-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
parent
2ce3ba291f
commit
5b48d72730
36 changed files with 200 additions and 144 deletions
|
@ -18,24 +18,34 @@
|
|||
package org.keycloak.adapters;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.auth.AuthSchemeProvider;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.client.CookieStore;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.conn.params.ConnRoutePNames;
|
||||
import org.apache.http.conn.scheme.PlainSocketFactory;
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
import org.apache.http.conn.scheme.SchemeRegistry;
|
||||
import org.apache.http.client.config.AuthSchemes;
|
||||
import org.apache.http.client.config.CookieSpecs;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.config.ConnectionConfig;
|
||||
import org.apache.http.config.Registry;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.config.SocketConfig;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
import org.apache.http.conn.ssl.StrictHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.X509HostnameVerifier;
|
||||
import org.apache.http.cookie.Cookie;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.impl.conn.SingleClientConnManager;
|
||||
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
|
||||
import org.apache.http.params.BasicHttpParams;
|
||||
import org.apache.http.params.HttpConnectionParams;
|
||||
import org.apache.http.cookie.CookieSpecProvider;
|
||||
import org.apache.http.impl.auth.SPNegoSchemeFactory;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.CookieSpecRegistries;
|
||||
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.impl.cookie.DefaultCookieSpecProvider;
|
||||
import org.keycloak.common.util.EnvUtil;
|
||||
import org.keycloak.common.util.KeystoreUtil;
|
||||
import org.keycloak.representations.adapters.config.AdapterHttpClientConfig;
|
||||
|
@ -50,15 +60,15 @@ import javax.net.ssl.X509TrustManager;
|
|||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.security.KeyStore;
|
||||
import java.security.Principal;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.http.client.params.ClientPNames;
|
||||
import org.apache.http.client.params.CookiePolicy;
|
||||
|
||||
/**
|
||||
* Abstraction for creating HttpClients. Allows SSL configuration.
|
||||
|
@ -67,6 +77,7 @@ import org.apache.http.client.params.CookiePolicy;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class HttpClientBuilder {
|
||||
|
||||
public static enum HostnameVerificationPolicy {
|
||||
/**
|
||||
* Hostname verification is not done on the server's certificate
|
||||
|
@ -118,7 +129,8 @@ public class HttpClientBuilder {
|
|||
protected long establishConnectionTimeout = -1;
|
||||
protected TimeUnit establishConnectionTimeoutUnits = TimeUnit.MILLISECONDS;
|
||||
protected HttpHost proxyHost;
|
||||
|
||||
private SPNegoSchemeFactory spNegoSchemeFactory;
|
||||
private boolean useSpNego;
|
||||
|
||||
/**
|
||||
* Socket inactivity timeout
|
||||
|
@ -240,6 +252,16 @@ public class HttpClientBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
public HttpClientBuilder spNegoSchemeFactory(SPNegoSchemeFactory spnegoSchemeFactory) {
|
||||
this.spNegoSchemeFactory = spnegoSchemeFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpClientBuilder useSPNego(boolean useSpnego) {
|
||||
this.useSpNego = useSpnego;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpClient build() {
|
||||
X509HostnameVerifier verifier = null;
|
||||
if (this.verifier != null) verifier = new VerifierWrapper(this.verifier);
|
||||
|
@ -257,7 +279,7 @@ public class HttpClientBuilder {
|
|||
}
|
||||
}
|
||||
try {
|
||||
SSLSocketFactory sslsf = null;
|
||||
ConnectionSocketFactory sslsf;
|
||||
SSLContext theContext = sslContext;
|
||||
if (disableTrustManager) {
|
||||
theContext = SSLContext.getInstance("SSL");
|
||||
|
@ -274,40 +296,85 @@ public class HttpClientBuilder {
|
|||
tlsContext.init(null, null, null);
|
||||
sslsf = new SniSSLSocketFactory(tlsContext, verifier);
|
||||
}
|
||||
SchemeRegistry registry = new SchemeRegistry();
|
||||
registry.register(
|
||||
new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
|
||||
Scheme httpsScheme = new Scheme("https", 443, sslsf);
|
||||
registry.register(httpsScheme);
|
||||
ClientConnectionManager cm = null;
|
||||
|
||||
RegistryBuilder<ConnectionSocketFactory> sf = RegistryBuilder.create();
|
||||
|
||||
sf.register("http", PlainConnectionSocketFactory.getSocketFactory());
|
||||
sf.register("https", sslsf);
|
||||
|
||||
HttpClientConnectionManager cm;
|
||||
|
||||
if (connectionPoolSize > 0) {
|
||||
ThreadSafeClientConnManager tcm = new ThreadSafeClientConnManager(registry, connectionTTL, connectionTTLUnit);
|
||||
PoolingHttpClientConnectionManager tcm = new PoolingHttpClientConnectionManager(sf.build());
|
||||
tcm.setMaxTotal(connectionPoolSize);
|
||||
if (maxPooledPerRoute == 0) maxPooledPerRoute = connectionPoolSize;
|
||||
tcm.setDefaultMaxPerRoute(maxPooledPerRoute);
|
||||
cm = tcm;
|
||||
|
||||
} else {
|
||||
cm = new SingleClientConnManager(registry);
|
||||
cm = new BasicHttpClientConnectionManager(sf.build());
|
||||
}
|
||||
BasicHttpParams params = new BasicHttpParams();
|
||||
params.setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);
|
||||
|
||||
SocketConfig.Builder socketConfig = SocketConfig.copy(SocketConfig.DEFAULT);
|
||||
ConnectionConfig.Builder connConfig = ConnectionConfig.copy(ConnectionConfig.DEFAULT);
|
||||
RequestConfig.Builder requestConfig = RequestConfig.copy(RequestConfig.DEFAULT);
|
||||
|
||||
if (proxyHost != null) {
|
||||
params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxyHost);
|
||||
requestConfig.setProxy(new HttpHost(proxyHost));
|
||||
}
|
||||
|
||||
if (socketTimeout > -1) {
|
||||
HttpConnectionParams.setSoTimeout(params, (int) socketTimeoutUnits.toMillis(socketTimeout));
|
||||
requestConfig.setSocketTimeout((int) socketTimeoutUnits.toMillis(socketTimeout));
|
||||
|
||||
}
|
||||
if (establishConnectionTimeout > -1) {
|
||||
HttpConnectionParams.setConnectionTimeout(params, (int) establishConnectionTimeoutUnits.toMillis(establishConnectionTimeout));
|
||||
requestConfig.setConnectTimeout((int) establishConnectionTimeoutUnits.toMillis(establishConnectionTimeout));
|
||||
}
|
||||
|
||||
Registry<CookieSpecProvider> cookieSpecs = CookieSpecRegistries.createDefaultBuilder()
|
||||
.register(CookieSpecs.DEFAULT, new DefaultCookieSpecProvider()).build();
|
||||
|
||||
if (useSpNego) {
|
||||
requestConfig.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.SPNEGO));
|
||||
}
|
||||
|
||||
org.apache.http.impl.client.HttpClientBuilder clientBuilder = org.apache.http.impl.client.HttpClientBuilder.create()
|
||||
.setDefaultSocketConfig(socketConfig.build())
|
||||
.setDefaultConnectionConfig(connConfig.build())
|
||||
.setDefaultRequestConfig(requestConfig.build())
|
||||
.setDefaultCookieSpecRegistry(cookieSpecs)
|
||||
.setConnectionManager(cm);
|
||||
|
||||
if (spNegoSchemeFactory != null) {
|
||||
RegistryBuilder<AuthSchemeProvider> authSchemes = RegistryBuilder.create();
|
||||
|
||||
authSchemes.register(AuthSchemes.SPNEGO, spNegoSchemeFactory);
|
||||
|
||||
clientBuilder.setDefaultAuthSchemeRegistry(authSchemes.build());
|
||||
}
|
||||
|
||||
if (useSpNego) {
|
||||
Credentials fake = new Credentials() {
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
credentialsProvider.setCredentials(AuthScope.ANY, fake);
|
||||
clientBuilder.setDefaultCredentialsProvider(credentialsProvider);
|
||||
}
|
||||
DefaultHttpClient client = new DefaultHttpClient(cm, params);
|
||||
|
||||
if (disableCookieCache) {
|
||||
client.setCookieStore(new CookieStore() {
|
||||
clientBuilder.setDefaultCookieStore(new CookieStore() {
|
||||
@Override
|
||||
public void addCookie(Cookie cookie) {
|
||||
//To change body of implemented methods use File | Settings | File Templates.
|
||||
|
@ -330,7 +397,7 @@ public class HttpClientBuilder {
|
|||
});
|
||||
|
||||
}
|
||||
return client;
|
||||
return clientBuilder.build();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
package org.keycloak.adapters;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.Configurable;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
|
||||
import org.apache.http.params.CoreConnectionPNames;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
|
@ -37,6 +39,9 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
* @author <a href="mailto:brad.culley@spartasystems.com">Brad Culley</a>
|
||||
|
@ -69,7 +74,22 @@ public class KeycloakDeploymentBuilderTest {
|
|||
assertFalse(deployment.isOAuthQueryParameterEnabled());
|
||||
assertEquals("234234-234234-234234", deployment.getResourceCredentials().get("secret"));
|
||||
assertEquals(ClientIdAndSecretCredentialsProvider.PROVIDER_ID, deployment.getClientAuthenticator().getId());
|
||||
assertEquals(20, ((ThreadSafeClientConnManager) deployment.getClient().getConnectionManager()).getMaxTotal());
|
||||
HttpClient client = deployment.getClient();
|
||||
int maxPoolConnections = -1;
|
||||
Field connManager = null;
|
||||
|
||||
try {
|
||||
connManager = client.getClass().getDeclaredField("connManager");
|
||||
connManager.setAccessible(true);
|
||||
maxPoolConnections = ((PoolingHttpClientConnectionManager) connManager.get(client)).getMaxTotal();
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Failed to get max pool connections", cause);
|
||||
} finally {
|
||||
connManager.setAccessible(false);
|
||||
}
|
||||
|
||||
|
||||
assertEquals(20, maxPoolConnections);
|
||||
assertEquals(RelativeUrlsUsed.NEVER, deployment.getRelativeUrls());
|
||||
assertTrue(deployment.isAlwaysRefreshToken());
|
||||
assertTrue(deployment.isRegisterNodeAtStartup());
|
||||
|
@ -113,8 +133,8 @@ public class KeycloakDeploymentBuilderTest {
|
|||
HttpClient client = deployment.getClient();
|
||||
assertThat(client, CoreMatchers.notNullValue());
|
||||
|
||||
long socketTimeout = client.getParams().getIntParameter(CoreConnectionPNames.SO_TIMEOUT, -2);
|
||||
long connectionTimeout = client.getParams().getIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, -2);
|
||||
long socketTimeout = ((Configurable) client).getConfig().getSocketTimeout();
|
||||
long connectionTimeout = ((Configurable) client).getConfig().getConnectTimeout();
|
||||
|
||||
assertThat(socketTimeout, CoreMatchers.is(2000L));
|
||||
assertThat(connectionTimeout, CoreMatchers.is(6000L));
|
||||
|
|
|
@ -567,10 +567,11 @@ public class KeycloakInstalled {
|
|||
}
|
||||
|
||||
protected ResteasyClient createResteasyClient() {
|
||||
return new ResteasyClientBuilder()
|
||||
return ((ResteasyClientBuilder) ResteasyClientBuilder.newBuilder())
|
||||
.connectionCheckoutTimeout(1, TimeUnit.HOURS)
|
||||
.connectionTTL(1, TimeUnit.HOURS)
|
||||
.socketTimeout(1, TimeUnit.HOURS)
|
||||
.connectTimeout(1, TimeUnit.HOURS)
|
||||
.readTimeout(1, TimeUnit.HOURS)
|
||||
.disableTrustManager().build();
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -135,7 +135,7 @@
|
|||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>org.jboss.resteasy:resteasy-jaxrs</artifact>
|
||||
<artifact>org.jboss.resteasy:resteasy-core</artifact>
|
||||
<includes>
|
||||
<include>**/**</include>
|
||||
</includes>
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider
|
||||
org.jboss.resteasy.plugins.providers.DataSourceProvider
|
||||
org.jboss.resteasy.plugins.providers.DocumentProvider
|
||||
org.jboss.resteasy.plugins.providers.DefaultTextPlain
|
||||
org.jboss.resteasy.plugins.providers.StringTextStar
|
||||
org.jboss.resteasy.plugins.providers.SourceProvider
|
||||
org.jboss.resteasy.plugins.providers.InputStreamProvider
|
||||
org.jboss.resteasy.plugins.providers.ReaderProvider
|
||||
org.jboss.resteasy.plugins.providers.ByteArrayProvider
|
||||
org.jboss.resteasy.plugins.providers.FormUrlEncodedProvider
|
||||
org.jboss.resteasy.plugins.providers.JaxrsFormProvider
|
||||
org.jboss.resteasy.plugins.providers.FileProvider
|
||||
org.jboss.resteasy.plugins.providers.FileRangeWriter
|
||||
org.jboss.resteasy.plugins.providers.StreamingOutputProvider
|
||||
org.jboss.resteasy.plugins.providers.IIOImageProvider
|
||||
org.jboss.resteasy.plugins.providers.SerializableProvider
|
||||
org.jboss.resteasy.plugins.interceptors.CacheControlFeature
|
||||
org.jboss.resteasy.plugins.interceptors.encoding.AcceptEncodingGZIPInterceptor
|
||||
org.jboss.resteasy.plugins.interceptors.encoding.AcceptEncodingGZIPFilter
|
||||
org.jboss.resteasy.plugins.interceptors.encoding.ClientContentEncodingAnnotationFeature
|
||||
org.jboss.resteasy.plugins.interceptors.encoding.GZIPDecodingInterceptor
|
||||
org.jboss.resteasy.plugins.interceptors.encoding.GZIPEncodingInterceptor
|
||||
org.jboss.resteasy.plugins.interceptors.encoding.ServerContentEncodingAnnotationFeature
|
|
@ -90,7 +90,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<!-- needed for LegacyExportImportManager that is calling ValidationUtil.validateClient (which is in server-spi-private) might throw a BadRequestException -->
|
||||
<!-- see: https://github.com/hmlnarik/keycloak/pull/23#discussion_r862293798 -->
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
<!-- needed for MapExportImportManager that is calling ValidationUtil.validateClient (which is in server-spi-private) might throw a BadRequestException -->
|
||||
<!-- see: https://github.com/hmlnarik/keycloak/pull/23#discussion_r862293798 -->
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
4
pom.xml
4
pom.xml
|
@ -105,7 +105,7 @@
|
|||
<jboss.spec.javax.xml.bind.jboss-jaxb-api_2.3_spec.version>2.0.1.Final</jboss.spec.javax.xml.bind.jboss-jaxb-api_2.3_spec.version>
|
||||
<jboss.spec.javax.servlet.jsp.jboss-jsp-api_2.3_spec.version>2.0.0.Final</jboss.spec.javax.servlet.jsp.jboss-jsp-api_2.3_spec.version>
|
||||
<log4j.version>1.2.17</log4j.version>
|
||||
<resteasy.version>3.15.1.Final</resteasy.version>
|
||||
<resteasy.version>4.7.4.Final</resteasy.version>
|
||||
<resteasy.undertow.version>${resteasy.version}</resteasy.undertow.version>
|
||||
<owasp.html.sanitizer.version>20211018.2</owasp.html.sanitizer.version>
|
||||
<slf4j-api.version>1.7.30</slf4j-api.version>
|
||||
|
@ -400,7 +400,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<version>${resteasy.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
package org.keycloak.models;
|
||||
|
||||
import org.jboss.resteasy.specimpl.ResteasyUriBuilder;
|
||||
import org.jboss.resteasy.spi.ResteasyUriBuilder;
|
||||
import org.keycloak.urls.HostnameProvider;
|
||||
import org.keycloak.urls.UrlType;
|
||||
|
||||
|
|
|
@ -107,7 +107,12 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -37,7 +37,7 @@ public class DBAllocatorServiceClient {
|
|||
|
||||
this.allocatorServletURI = URI.create(allocatorServletURI);
|
||||
this.retryPolicy = retryPolicy != null ? retryPolicy : new IncrementalBackoffRetryPolicy();
|
||||
this.restClient = new ResteasyClientBuilder().httpEngine(createEngine()).build();
|
||||
this.restClient = ((ResteasyClientBuilder) ResteasyClientBuilder.newBuilder()).httpEngine(createEngine()).build();
|
||||
}
|
||||
|
||||
private final ApacheHttpClient43Engine createEngine() {
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
|
|
|
@ -120,12 +120,7 @@
|
|||
</artifactItem>
|
||||
<artifactItem>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<version>${tomcat.resteasy.version}</version>
|
||||
</artifactItem>
|
||||
<artifactItem>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-servlet-initializer</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<version>${tomcat.resteasy.version}</version>
|
||||
</artifactItem>
|
||||
<artifactItem>
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.jboss.arquillian.container.spi.client.protocol.metadata.HTTPContext;
|
|||
import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData;
|
||||
import org.jboss.arquillian.container.spi.client.protocol.metadata.Servlet;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.core.ResteasyDeploymentImpl;
|
||||
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
|
||||
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||
import org.jboss.shrinkwrap.api.Archive;
|
||||
|
@ -139,7 +140,7 @@ public class UndertowAppServer implements DeployableContainer<UndertowAppServerC
|
|||
} else if (applicationClassNode.isPresent()) {
|
||||
String applicationPath = applicationClassNode.get().getPath().get();
|
||||
|
||||
ResteasyDeployment deployment = new ResteasyDeployment();
|
||||
ResteasyDeployment deployment = new ResteasyDeploymentImpl();
|
||||
deployment.setApplicationClass(extractClassName(applicationPath));
|
||||
di = new UndertowDeployerHelper().getDeploymentInfo(configuration, (WebArchive) archive, undertow.undertowDeployment(deployment));
|
||||
} else {
|
||||
|
@ -253,7 +254,7 @@ public class UndertowAppServer implements DeployableContainer<UndertowAppServerC
|
|||
.filter(clazz -> clazz.isAnnotationPresent(Path.class))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
ResteasyDeployment deployment = new ResteasyDeployment();
|
||||
ResteasyDeployment deployment = new ResteasyDeploymentImpl();
|
||||
deployment.setApplication(new RestSamlApplicationConfig(classes));
|
||||
return deployment;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.jboss.arquillian.container.spi.client.protocol.metadata.HTTPContext;
|
|||
import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData;
|
||||
import org.jboss.arquillian.container.spi.client.protocol.metadata.Servlet;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.core.ResteasyDeploymentImpl;
|
||||
import org.jboss.resteasy.plugins.server.servlet.ResteasyContextParameters;
|
||||
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
|
||||
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||
|
@ -81,19 +82,17 @@ public class KeycloakOnUndertow implements DeployableContainer<KeycloakOnUnderto
|
|||
Map<String, String> deployedArchivesToContextPath = new ConcurrentHashMap<>();
|
||||
|
||||
private DeploymentInfo createAuthServerDeploymentInfo() {
|
||||
ResteasyDeployment deployment = new ResteasyDeployment();
|
||||
ResteasyDeployment deployment = new ResteasyDeploymentImpl();
|
||||
deployment.setApplicationClass(KeycloakApplication.class.getName());
|
||||
|
||||
// RESTEASY-2034
|
||||
deployment.setProperty(ResteasyContextParameters.RESTEASY_DISABLE_HTML_SANITIZER, true);
|
||||
|
||||
// Prevent double gzip encoding of resources
|
||||
deployment.getDisabledProviderClasses().add("org.jboss.resteasy.plugins.interceptors.encoding.GZIPEncodingInterceptor");
|
||||
|
||||
DeploymentInfo di = undertow.undertowDeployment(deployment);
|
||||
di.setClassLoader(getClass().getClassLoader());
|
||||
di.setContextPath("/auth");
|
||||
di.setDeploymentName("Keycloak");
|
||||
di.setDefaultEncoding("UTF-8");
|
||||
if (configuration.getKeycloakConfigPropertyOverridesMap() != null) {
|
||||
try {
|
||||
di.addInitParameter(JsonConfigProviderFactory.SERVER_CONTEXT_CONFIG_PROPERTY_OVERRIDES,
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
<!-- wherever this is being deployed, the Servlet API spec should already be there.
|
||||
Therefore, make this provided to avoid mixing APIs on the target -->
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
@ -44,7 +47,11 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
|
|
|
@ -45,7 +45,7 @@ public class KeycloakTestingClient implements AutoCloseable {
|
|||
if (resteasyClient != null) {
|
||||
client = resteasyClient;
|
||||
} else {
|
||||
ResteasyClientBuilder resteasyClientBuilder = new ResteasyClientBuilder();
|
||||
ResteasyClientBuilder resteasyClientBuilder = (ResteasyClientBuilder) ResteasyClientBuilder.newBuilder();
|
||||
resteasyClientBuilder.connectionPoolSize(10);
|
||||
if (serverUrl.startsWith("https")) {
|
||||
// Disable PKIX path validation errors when running tests using SSL
|
||||
|
|
|
@ -35,16 +35,15 @@ import org.apache.http.conn.HttpClientConnectionManager;
|
|||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.ssl.SSLContexts;
|
||||
import org.jboss.resteasy.client.jaxrs.ClientHttpEngine;
|
||||
import org.jboss.resteasy.client.jaxrs.ClientHttpEngineBuilder43;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.engines.ClientHttpEngineBuilder43;
|
||||
import org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
import org.keycloak.models.Constants;
|
||||
|
||||
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.ADMIN;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
|
||||
import static org.keycloak.testsuite.utils.io.IOUtil.PROJECT_BUILD_DIRECTORY;
|
||||
|
@ -117,7 +116,7 @@ public class AdminClientUtil {
|
|||
}
|
||||
|
||||
public static ResteasyClient createResteasyClient(boolean ignoreUnknownProperties, Boolean followRedirects) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException {
|
||||
ResteasyClientBuilder resteasyClientBuilder = new ResteasyClientBuilder();
|
||||
ResteasyClientBuilder resteasyClientBuilder = (ResteasyClientBuilder) ResteasyClientBuilder.newBuilder();
|
||||
|
||||
if ("true".equals(System.getProperty("auth.server.ssl.required"))) {
|
||||
File trustore = new File(PROJECT_BUILD_DIRECTORY, "dependency/keystore/keycloak.truststore");
|
||||
|
@ -187,7 +186,7 @@ public class AdminClientUtil {
|
|||
engine = super.createEngine(cm, rcBuilder, defaultProxy, responseBufferSize, verifier, theContext);
|
||||
}
|
||||
if (followRedirects != null) {
|
||||
((ApacheHttpClient4Engine) engine).setFollowRedirects(followRedirects);
|
||||
engine.setFollowRedirects(followRedirects);
|
||||
}
|
||||
return engine;
|
||||
}
|
||||
|
|
|
@ -280,7 +280,7 @@ public class ImpersonationTest extends AbstractKeycloakTest {
|
|||
|
||||
// Return the SSO cookie from the impersonated session
|
||||
protected Set<Cookie> testSuccessfulImpersonation(String admin, String adminRealm) {
|
||||
ResteasyClientBuilder resteasyClientBuilder = new ResteasyClientBuilder();
|
||||
ResteasyClientBuilder resteasyClientBuilder = (ResteasyClientBuilder) ResteasyClientBuilder.newBuilder();
|
||||
resteasyClientBuilder.connectionPoolSize(10);
|
||||
resteasyClientBuilder.httpEngine(AdminClientUtil.getCustomClientHttpEngine(resteasyClientBuilder, 10, null));
|
||||
ResteasyClient resteasyClient = resteasyClientBuilder.build();
|
||||
|
@ -392,7 +392,7 @@ public class ImpersonationTest extends AbstractKeycloakTest {
|
|||
|
||||
// Return the SSO cookie from the impersonated session
|
||||
protected Set<Cookie> testSuccessfulServiceAccountImpersonation(UserRepresentation serviceAccount, String serviceAccountRealm) {
|
||||
ResteasyClientBuilder resteasyClientBuilder = new ResteasyClientBuilder();
|
||||
ResteasyClientBuilder resteasyClientBuilder = (ResteasyClientBuilder) ResteasyClientBuilder.newBuilder();
|
||||
resteasyClientBuilder.connectionPoolSize(10);
|
||||
resteasyClientBuilder.httpEngine(AdminClientUtil.getCustomClientHttpEngine(resteasyClientBuilder, 10, null));
|
||||
ResteasyClient resteasyClient = resteasyClientBuilder.build();
|
||||
|
|
|
@ -21,7 +21,6 @@ import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
|
|||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||
|
||||
import java.net.URI;
|
||||
import java.security.Principal;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -35,16 +34,13 @@ import javax.naming.directory.InitialDirContext;
|
|||
import javax.security.sasl.Sasl;
|
||||
import javax.ws.rs.core.Response;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.client.config.AuthSchemes;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.ietf.jgss.GSSCredential;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
|
||||
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
|
@ -262,33 +258,14 @@ public abstract class AbstractKerberosTest extends AbstractAuthTest {
|
|||
cleanupApacheHttpClient();
|
||||
}
|
||||
|
||||
DefaultHttpClient httpClient = (DefaultHttpClient) new HttpClientBuilder()
|
||||
HttpClient httpClient = new HttpClientBuilder()
|
||||
.disableCookieCache(false)
|
||||
.spNegoSchemeFactory(spnegoSchemeFactory)
|
||||
.useSPNego(useSpnego)
|
||||
.build();
|
||||
|
||||
httpClient.getAuthSchemes().register(AuthSchemes.SPNEGO, spnegoSchemeFactory);
|
||||
|
||||
if (useSpnego) {
|
||||
Credentials fake = new Credentials() {
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
httpClient.getCredentialsProvider().setCredentials(
|
||||
new AuthScope(null, -1, null),
|
||||
fake);
|
||||
}
|
||||
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
|
||||
client = new ResteasyClientBuilder().httpEngine(engine).build();
|
||||
ApacheHttpClient43Engine engine = new ApacheHttpClient43Engine(httpClient);
|
||||
client = ((ResteasyClientBuilder) ResteasyClientBuilder.newBuilder()).httpEngine(engine).build();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.apache.http.auth.Credentials;
|
|||
import org.apache.http.impl.auth.SPNegoScheme;
|
||||
import org.apache.http.impl.auth.SPNegoSchemeFactory;
|
||||
import org.apache.http.params.HttpParams;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.ietf.jgss.GSSContext;
|
||||
import org.ietf.jgss.GSSException;
|
||||
import org.ietf.jgss.GSSManager;
|
||||
|
@ -66,6 +67,10 @@ public class KeycloakSPNegoSchemeFactory extends SPNegoSchemeFactory {
|
|||
return new KeycloakSPNegoScheme(isStripPort(), isUseCanonicalHostname());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthScheme create(HttpContext context) {
|
||||
return new KeycloakSPNegoScheme(isStripPort(), isUseCanonicalHostname());
|
||||
}
|
||||
|
||||
public class KeycloakSPNegoScheme extends SPNegoScheme {
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
|||
import org.hamcrest.Matchers;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
|
||||
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
|
@ -126,8 +126,8 @@ public class LoginPageTest extends AbstractI18NTest {
|
|||
ProfileAssume.assumeCommunity();
|
||||
|
||||
try(CloseableHttpClient httpClient = (CloseableHttpClient) new HttpClientBuilder().build()) {
|
||||
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
|
||||
ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
|
||||
ApacheHttpClient43Engine engine = new ApacheHttpClient43Engine(httpClient);
|
||||
ResteasyClient client = ((ResteasyClientBuilder) ResteasyClientBuilder.newBuilder()).httpEngine(engine).build();
|
||||
|
||||
loginPage.open();
|
||||
|
||||
|
@ -264,12 +264,12 @@ public class LoginPageTest extends AbstractI18NTest {
|
|||
final String realmLocalizationMessageValue = "Localization Test";
|
||||
|
||||
try(CloseableHttpClient httpClient = (CloseableHttpClient) new HttpClientBuilder().build()) {
|
||||
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
|
||||
ApacheHttpClient43Engine engine = new ApacheHttpClient43Engine(httpClient);
|
||||
|
||||
testRealm().localization().saveRealmLocalizationText(locale, realmLocalizationMessageKey,
|
||||
realmLocalizationMessageValue);
|
||||
|
||||
ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
|
||||
ResteasyClient client = ((ResteasyClientBuilder) ResteasyClientBuilder.newBuilder()).httpEngine(engine).build();
|
||||
|
||||
loginPage.open();
|
||||
|
||||
|
|
|
@ -35,6 +35,12 @@
|
|||
<artifactId>junit</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest</artifactId>
|
||||
|
|
|
@ -130,7 +130,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
|
|
|
@ -71,10 +71,6 @@
|
|||
<artifactId>dom4j</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.ws.rs</groupId>
|
||||
<artifactId>jboss-jaxrs-api_2.1_spec</artifactId>
|
||||
|
@ -85,7 +81,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<artifactId>resteasy-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>log4j</groupId>
|
||||
|
|
|
@ -23,7 +23,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import javax.servlet.ServletContext;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.common.util.Resteasy;
|
||||
import org.keycloak.common.util.SystemEnvProperties;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
|
@ -38,7 +38,7 @@ public class JsonConfigProviderFactory extends org.keycloak.services.util.JsonCo
|
|||
|
||||
private Map<String, String> getPropertyOverrides() {
|
||||
|
||||
ServletContext context = ResteasyProviderFactory.getContextData(ServletContext.class);
|
||||
ServletContext context = Resteasy.getContextData(ServletContext.class);
|
||||
Map<String, String> propertyOverridesMap = new HashMap<>();
|
||||
String propertyOverrides = context.getInitParameter(SERVER_CONTEXT_CONFIG_PROPERTY_OVERRIDES);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import io.undertow.servlet.api.DefaultServletConfig;
|
|||
import io.undertow.servlet.api.DeploymentInfo;
|
||||
import io.undertow.servlet.api.FilterInfo;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.core.ResteasyDeploymentImpl;
|
||||
import org.jboss.resteasy.plugins.server.servlet.ResteasyContextParameters;
|
||||
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
|
||||
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||
|
@ -396,7 +397,7 @@ public class KeycloakServer {
|
|||
public void start() throws Throwable {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
ResteasyDeployment deployment = new ResteasyDeployment();
|
||||
ResteasyDeployment deployment = new ResteasyDeploymentImpl();
|
||||
|
||||
deployment.setApplicationClass(KeycloakApplication.class.getName());
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package org.keycloak.testsuite;
|
||||
|
||||
import org.jboss.resteasy.core.Dispatcher;
|
||||
import org.jboss.resteasy.core.ResteasyContext;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.common.util.ResteasyProvider;
|
||||
|
||||
public class Resteasy3Provider implements ResteasyProvider {
|
||||
public class Resteasy4Provider implements ResteasyProvider {
|
||||
|
||||
@Override
|
||||
public <R> R getContextData(Class<R> type) {
|
||||
|
@ -13,18 +13,18 @@ public class Resteasy3Provider implements ResteasyProvider {
|
|||
|
||||
@Override
|
||||
public void pushDefaultContextObject(Class type, Object instance) {
|
||||
ResteasyProviderFactory.getInstance().getContextData(Dispatcher.class).getDefaultContextObjects()
|
||||
ResteasyProviderFactory.getInstance().getContextData(org.jboss.resteasy.spi.Dispatcher.class).getDefaultContextObjects()
|
||||
.put(type, instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushContext(Class type, Object instance) {
|
||||
ResteasyProviderFactory.getInstance().pushContext(type, instance);
|
||||
ResteasyContext.pushContext(type, instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearContextData() {
|
||||
ResteasyProviderFactory.getInstance().clearContextData();
|
||||
ResteasyContext.clearContextData();
|
||||
}
|
||||
|
||||
}
|
|
@ -1 +1 @@
|
|||
org.keycloak.testsuite.Resteasy3Provider
|
||||
org.keycloak.testsuite.Resteasy4Provider
|
Loading…
Reference in a new issue