Remove remaining servlet filter adapter bits
Closes #29225 Signed-off-by: Douglas Palmer <dpalmer@redhat.com>
This commit is contained in:
parent
e0176a7e31
commit
8a0322cc13
10 changed files with 0 additions and 1756 deletions
|
@ -1,141 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
~ and other contributors as indicated by the @author tags.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-saml-jakarta-servlet-filter-adapter</artifactId>
|
||||
<name>Keycloak SAML Jakarta Servlet Filter</name>
|
||||
<description/>
|
||||
|
||||
<!--
|
||||
NOTE: This maven module is generated using original: servlet-filter
|
||||
@see: ${jakarta-transformer-sources}
|
||||
Reason is the transition to Jakarta APIs.
|
||||
-->
|
||||
<properties>
|
||||
<jakarta-transformer-sources>${project.basedir}/../servlet-filter/src</jakarta-transformer-sources>
|
||||
<jakarta-transformer-target>${project.basedir}/src</jakarta-transformer-target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-jakarta-servlet-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk18on</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-adapter-api-public</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-adapter-core-jakarta</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-crypto-default</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>transform</id>
|
||||
<phase>initialize</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<target>
|
||||
<property name="plugin_classpath" refid="maven.plugin.classpath" />
|
||||
<java classname="org.eclipse.transformer.jakarta.JakartaTransformer">
|
||||
<arg value="-o" />
|
||||
<arg value="${jakarta-transformer-sources}" />
|
||||
<arg value="${jakarta-transformer-target}" />
|
||||
<classpath>
|
||||
<pathelement path="${plugin_classpath}" />
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.transformer</groupId>
|
||||
<artifactId>org.eclipse.transformer.cli</artifactId>
|
||||
<version>0.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ant-contrib</groupId>
|
||||
<artifactId>ant-contrib</artifactId>
|
||||
<version>1.0b3</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>ant</groupId>
|
||||
<artifactId>ant</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -36,7 +36,6 @@
|
|||
<module>core-jakarta</module>
|
||||
<module>undertow</module>
|
||||
<module>wildfly</module>
|
||||
<module>jakarta-servlet-filter</module>
|
||||
<module>wildfly-elytron</module>
|
||||
<module>wildfly-elytron-jakarta</module>
|
||||
</modules>
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
~ and other contributors as indicated by the @author tags.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-jakarta-servlet-adapter-spi</artifactId>
|
||||
<name>Keycloak Jakarta Servlet Integration</name>
|
||||
<description/>
|
||||
|
||||
<properties>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.servlet.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
<keycloak.osgi.fragment>${project.groupId}.keycloak-jakarta-servlet-filter-adapter</keycloak.osgi.fragment>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
<Fragment-Host>${keycloak.osgi.fragment}</Fragment-Host>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -1,433 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.servlet;
|
||||
|
||||
import org.keycloak.adapters.spi.AdapterSessionStore;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.spi.KeycloakAccount;
|
||||
import org.keycloak.common.util.Encode;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletInputStream;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import jakarta.servlet.ReadListener;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.security.Principal;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class FilterSessionStore implements AdapterSessionStore {
|
||||
public static final String REDIRECT_URI = "__REDIRECT_URI";
|
||||
public static final String SAVED_METHOD = "__SAVED_METHOD";
|
||||
public static final String SAVED_HEADERS = "__SAVED_HEADERS";
|
||||
public static final String SAVED_BODY = "__SAVED_BODY";
|
||||
protected final HttpServletRequest request;
|
||||
protected final HttpFacade facade;
|
||||
protected final int maxBuffer;
|
||||
protected byte[] restoredBuffer = null;
|
||||
protected boolean needRequestRestore;
|
||||
|
||||
public FilterSessionStore(HttpServletRequest request, HttpFacade facade, int maxBuffer) {
|
||||
this.request = request;
|
||||
this.facade = facade;
|
||||
this.maxBuffer = maxBuffer;
|
||||
}
|
||||
|
||||
public void clearSavedRequest(HttpSession session) {
|
||||
session.removeAttribute(REDIRECT_URI);
|
||||
session.removeAttribute(SAVED_METHOD);
|
||||
session.removeAttribute(SAVED_HEADERS);
|
||||
session.removeAttribute(SAVED_BODY);
|
||||
}
|
||||
|
||||
public void servletRequestLogout() {
|
||||
|
||||
}
|
||||
|
||||
public static String getCharsetFromContentType(String contentType) {
|
||||
|
||||
if (contentType == null)
|
||||
return (null);
|
||||
int start = contentType.indexOf("charset=");
|
||||
if (start < 0)
|
||||
return (null);
|
||||
String encoding = contentType.substring(start + 8);
|
||||
int end = encoding.indexOf(';');
|
||||
if (end >= 0)
|
||||
encoding = encoding.substring(0, end);
|
||||
encoding = encoding.trim();
|
||||
if ((encoding.length() > 2) && (encoding.startsWith("\""))
|
||||
&& (encoding.endsWith("\"")))
|
||||
encoding = encoding.substring(1, encoding.length() - 1);
|
||||
return (encoding.trim());
|
||||
|
||||
}
|
||||
|
||||
|
||||
public HttpServletRequestWrapper buildWrapper(HttpSession session, final KeycloakAccount account) {
|
||||
if (needRequestRestore) {
|
||||
final String method = (String)session.getAttribute(SAVED_METHOD);
|
||||
final byte[] body = (byte[])session.getAttribute(SAVED_BODY);
|
||||
final MultivaluedHashMap<String, String> headers = (MultivaluedHashMap<String, String>)session.getAttribute(SAVED_HEADERS);
|
||||
clearSavedRequest(session);
|
||||
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) {
|
||||
protected MultivaluedHashMap<String, String> parameters;
|
||||
|
||||
MultivaluedHashMap<String, String> getParams() {
|
||||
if (parameters != null) return parameters;
|
||||
|
||||
if (body == null) return new MultivaluedHashMap<String, String>();
|
||||
|
||||
String contentType = getContentType();
|
||||
if (contentType != null && contentType.toLowerCase().startsWith("application/x-www-form-urlencoded")) {
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(body);
|
||||
try {
|
||||
parameters = parseForm(is);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return parameters;
|
||||
|
||||
}
|
||||
@Override
|
||||
public boolean isUserInRole(String role) {
|
||||
return account.getRoles().contains(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return account.getPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
if (needRequestRestore) {
|
||||
return method;
|
||||
} else {
|
||||
return super.getMethod();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String name) {
|
||||
if (needRequestRestore && headers != null) {
|
||||
return headers.getFirst(name.toLowerCase());
|
||||
}
|
||||
return super.getHeader(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getHeaders(String name) {
|
||||
if (needRequestRestore && headers != null) {
|
||||
List<String> values = headers.getList(name.toLowerCase());
|
||||
if (values == null) return Collections.emptyEnumeration();
|
||||
else return Collections.enumeration(values);
|
||||
}
|
||||
return super.getHeaders(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getHeaderNames() {
|
||||
if (needRequestRestore && headers != null) {
|
||||
return Collections.enumeration(headers.keySet());
|
||||
}
|
||||
return super.getHeaderNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
if (needRequestRestore && body != null) {
|
||||
final ByteArrayInputStream is = new ByteArrayInputStream(body);
|
||||
return new ServletInputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return is.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return is.available() == 0; // Check if the underlying stream has data available.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return true; // Return true to indicate that the data is always ready to be read.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener readListener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
return super.getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout() throws ServletException {
|
||||
servletRequestLogout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDateHeader(String name) {
|
||||
if (!needRequestRestore) return super.getDateHeader(name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntHeader(String name) {
|
||||
if (!needRequestRestore) return super.getIntHeader(name);
|
||||
String value = getHeader(name);
|
||||
if (value == null) return -1;
|
||||
return Integer.valueOf(value);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String name) {
|
||||
if (!needRequestRestore) return super.getParameterValues(name);
|
||||
MultivaluedHashMap<String, String> formParams = getParams();
|
||||
if (formParams == null) {
|
||||
return super.getParameterValues(name);
|
||||
}
|
||||
String[] values = request.getParameterValues(name);
|
||||
List<String> list = new LinkedList<>();
|
||||
if (values != null) {
|
||||
for (String val : values) list.add(val);
|
||||
}
|
||||
List<String> vals = formParams.get(name);
|
||||
if (vals != null) list.addAll(vals);
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getParameterNames() {
|
||||
if (!needRequestRestore) return super.getParameterNames();
|
||||
MultivaluedHashMap<String, String> formParams = getParams();
|
||||
if (formParams == null) {
|
||||
return super.getParameterNames();
|
||||
}
|
||||
Set<String> names = new HashSet<>();
|
||||
Enumeration<String> qnames = super.getParameterNames();
|
||||
while (qnames.hasMoreElements()) names.add(qnames.nextElement());
|
||||
names.addAll(formParams.keySet());
|
||||
return Collections.enumeration(names);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
if (!needRequestRestore) return super.getParameterMap();
|
||||
MultivaluedHashMap<String, String> formParams = getParams();
|
||||
if (formParams == null) {
|
||||
return super.getParameterMap();
|
||||
}
|
||||
Map<String, String[]> map = new HashMap<>();
|
||||
Enumeration<String> names = getParameterNames();
|
||||
while (names.hasMoreElements()) {
|
||||
String name = names.nextElement();
|
||||
String[] values = getParameterValues(name);
|
||||
if (values != null) {
|
||||
map.put(name, values);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String name) {
|
||||
if (!needRequestRestore) return super.getParameter(name);
|
||||
String param = super.getParameter(name);
|
||||
if (param != null) return param;
|
||||
MultivaluedHashMap<String, String> formParams = getParams();
|
||||
if (formParams == null) {
|
||||
return null;
|
||||
}
|
||||
return formParams.getFirst(name);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() throws IOException {
|
||||
if (!needRequestRestore) return super.getReader();
|
||||
return new BufferedReader(new InputStreamReader(getInputStream()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentLength() {
|
||||
if (!needRequestRestore) return super.getContentLength();
|
||||
String header = getHeader("content-length");
|
||||
if (header == null) return -1;
|
||||
return Integer.valueOf(header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
if (!needRequestRestore) return super.getContentType();
|
||||
return getHeader("content-type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacterEncoding() {
|
||||
if (!needRequestRestore) return super.getCharacterEncoding();
|
||||
return getCharsetFromContentType(getContentType());
|
||||
}
|
||||
|
||||
};
|
||||
return wrapper;
|
||||
} else {
|
||||
return new HttpServletRequestWrapper(request) {
|
||||
@Override
|
||||
public boolean isUserInRole(String role) {
|
||||
return account.getRoles().contains(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
if (account == null) return null;
|
||||
return account.getPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout() throws ServletException {
|
||||
servletRequestLogout();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public String getRedirectUri() {
|
||||
HttpSession session = request.getSession(true);
|
||||
return (String)session.getAttribute(REDIRECT_URI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreRequest() {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session == null) return false;
|
||||
return session.getAttribute(REDIRECT_URI) != null;
|
||||
}
|
||||
|
||||
public static MultivaluedHashMap<String, String> parseForm(InputStream entityStream)
|
||||
throws IOException
|
||||
{
|
||||
char[] buffer = new char[100];
|
||||
StringBuffer buf = new StringBuffer();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(entityStream));
|
||||
|
||||
int wasRead = 0;
|
||||
do
|
||||
{
|
||||
wasRead = reader.read(buffer, 0, 100);
|
||||
if (wasRead > 0) buf.append(buffer, 0, wasRead);
|
||||
} while (wasRead > -1);
|
||||
|
||||
String form = buf.toString();
|
||||
|
||||
MultivaluedHashMap<String, String> formData = new MultivaluedHashMap<String, String>();
|
||||
if ("".equals(form)) return formData;
|
||||
|
||||
String[] params = form.split("&");
|
||||
|
||||
for (String param : params)
|
||||
{
|
||||
if (param.indexOf('=') >= 0)
|
||||
{
|
||||
String[] nv = param.split("=");
|
||||
String val = nv.length > 1 ? nv[1] : "";
|
||||
formData.add(Encode.decode(nv[0]), Encode.decode(val));
|
||||
}
|
||||
else
|
||||
{
|
||||
formData.add(Encode.decode(param), "");
|
||||
}
|
||||
}
|
||||
return formData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void saveRequest() {
|
||||
HttpSession session = request.getSession(true);
|
||||
session.setAttribute(REDIRECT_URI, facade.getRequest().getURI());
|
||||
session.setAttribute(SAVED_METHOD, request.getMethod());
|
||||
MultivaluedHashMap<String, String> headers = new MultivaluedHashMap<>();
|
||||
Enumeration<String> names = request.getHeaderNames();
|
||||
while (names.hasMoreElements()) {
|
||||
String name = names.nextElement();
|
||||
Enumeration<String> values = request.getHeaders(name);
|
||||
while (values.hasMoreElements()) {
|
||||
headers.add(name.toLowerCase(), values.nextElement());
|
||||
}
|
||||
}
|
||||
session.setAttribute(SAVED_HEADERS, headers);
|
||||
if (request.getMethod().equalsIgnoreCase("GET")) {
|
||||
return;
|
||||
}
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
int totalRead = 0;
|
||||
try {
|
||||
InputStream is = request.getInputStream();
|
||||
|
||||
while ( (bytesRead = is.read(buffer) ) >= 0) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
totalRead += bytesRead;
|
||||
if (totalRead > maxBuffer) {
|
||||
throw new RuntimeException("max buffer reached on a saved request");
|
||||
}
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
byte[] body = os.toByteArray();
|
||||
// Only save the request body if there is something to save
|
||||
if (body.length > 0) {
|
||||
session.setAttribute(SAVED_BODY, body);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,268 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.servlet;
|
||||
|
||||
import org.keycloak.adapters.spi.AuthenticationError;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.spi.LogoutError;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.common.util.ServerCookie;
|
||||
import org.keycloak.common.util.UriUtils;
|
||||
|
||||
import javax.security.cert.X509Certificate;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ServletHttpFacade implements HttpFacade {
|
||||
protected final RequestFacade requestFacade = new RequestFacade();
|
||||
protected final ResponseFacade responseFacade = new ResponseFacade();
|
||||
protected HttpServletRequest request;
|
||||
protected HttpServletResponse response;
|
||||
protected MultivaluedHashMap<String, String> queryParameters;
|
||||
|
||||
public ServletHttpFacade(HttpServletRequest request, HttpServletResponse response) {
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
protected class RequestFacade implements Request {
|
||||
|
||||
private InputStream inputStream;
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return request.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getURI() {
|
||||
StringBuffer buf = request.getRequestURL();
|
||||
if (request.getQueryString() != null) {
|
||||
buf.append('?').append(request.getQueryString());
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRelativePath() {
|
||||
String uri = request.getRequestURI();
|
||||
String contextPath = request.getContextPath();
|
||||
String servletPath = uri.substring(uri.indexOf(contextPath) + contextPath.length());
|
||||
|
||||
if ("".equals(servletPath)) {
|
||||
servletPath = "/";
|
||||
}
|
||||
|
||||
return servletPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return request.isSecure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstParam(String param) {
|
||||
return request.getParameter(param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParamValue(String param) {
|
||||
if (queryParameters == null) {
|
||||
queryParameters = UriUtils.decodeQueryString(request.getQueryString());
|
||||
}
|
||||
return queryParameters.getFirst(param);
|
||||
}
|
||||
|
||||
public MultivaluedHashMap<String, String> getQueryParameters() {
|
||||
if (queryParameters == null) {
|
||||
queryParameters = UriUtils.decodeQueryString(request.getQueryString());
|
||||
}
|
||||
return queryParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cookie getCookie(String cookieName) {
|
||||
if (request.getCookies() == null) return null;
|
||||
jakarta.servlet.http.Cookie cookie = null;
|
||||
for (jakarta.servlet.http.Cookie c : request.getCookies()) {
|
||||
if (c.getName().equals(cookieName)) {
|
||||
cookie = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cookie == null) return null;
|
||||
return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String name) {
|
||||
return request.getHeader(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getHeaders(String name) {
|
||||
Enumeration<String> values = request.getHeaders(name);
|
||||
List<String> list = new LinkedList<>();
|
||||
while (values.hasMoreElements()) list.add(values.nextElement());
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return getInputStream(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream(boolean buffered) {
|
||||
if (inputStream != null) {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
if (buffered) {
|
||||
try {
|
||||
return inputStream = new BufferedInputStream(request.getInputStream());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return request.getInputStream();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteAddr() {
|
||||
return request.getRemoteAddr();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setError(AuthenticationError error) {
|
||||
request.setAttribute(AuthenticationError.class.getName(), error);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setError(LogoutError error) {
|
||||
request.setAttribute(LogoutError.class.getName(), error);
|
||||
}
|
||||
}
|
||||
public boolean isEnded() {
|
||||
return responseFacade.isEnded();
|
||||
}
|
||||
|
||||
protected class ResponseFacade implements Response {
|
||||
protected boolean ended;
|
||||
|
||||
@Override
|
||||
public void setStatus(int status) {
|
||||
response.setStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String name, String value) {
|
||||
response.addHeader(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String name, String value) {
|
||||
response.setHeader(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetCookie(String name, String path) {
|
||||
setCookie(name, "", path, null, 0, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) {
|
||||
StringBuilder cookieBuf = new StringBuilder();
|
||||
ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, null, maxAge, secure, httpOnly, null);
|
||||
String cookie = cookieBuf.toString();
|
||||
response.addHeader("Set-Cookie", cookie);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() {
|
||||
try {
|
||||
return response.getOutputStream();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int code) {
|
||||
try {
|
||||
response.sendError(code);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int code, String message) {
|
||||
try {
|
||||
response.sendError(code, message);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
ended = true;
|
||||
}
|
||||
|
||||
public boolean isEnded() {
|
||||
return ended;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Request getRequest() {
|
||||
return requestFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getResponse() {
|
||||
return responseFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain() {
|
||||
throw new IllegalStateException("Not supported yet");
|
||||
}
|
||||
}
|
|
@ -33,8 +33,6 @@
|
|||
<modules>
|
||||
<module>adapter-spi</module>
|
||||
<module>undertow-adapter-spi</module>
|
||||
<module>servlet-adapter-spi</module>
|
||||
<module>jakarta-servlet-adapter-spi</module>
|
||||
<module>jboss-adapter-core</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
~ and other contributors as indicated by the @author tags.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-servlet-adapter-spi</artifactId>
|
||||
<name>Keycloak Servlet Integration</name>
|
||||
<description/>
|
||||
|
||||
<properties>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.servlet.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
<keycloak.osgi.fragment>${project.groupId}.keycloak-servlet-filter-adapter</keycloak.osgi.fragment>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
<Fragment-Host>${keycloak.osgi.fragment}</Fragment-Host>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -1,418 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.servlet;
|
||||
|
||||
import org.keycloak.adapters.spi.AdapterSessionStore;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.spi.KeycloakAccount;
|
||||
import org.keycloak.common.util.Encode;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.security.Principal;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class FilterSessionStore implements AdapterSessionStore {
|
||||
public static final String REDIRECT_URI = "__REDIRECT_URI";
|
||||
public static final String SAVED_METHOD = "__SAVED_METHOD";
|
||||
public static final String SAVED_HEADERS = "__SAVED_HEADERS";
|
||||
public static final String SAVED_BODY = "__SAVED_BODY";
|
||||
protected final HttpServletRequest request;
|
||||
protected final HttpFacade facade;
|
||||
protected final int maxBuffer;
|
||||
protected byte[] restoredBuffer = null;
|
||||
protected boolean needRequestRestore;
|
||||
|
||||
public FilterSessionStore(HttpServletRequest request, HttpFacade facade, int maxBuffer) {
|
||||
this.request = request;
|
||||
this.facade = facade;
|
||||
this.maxBuffer = maxBuffer;
|
||||
}
|
||||
|
||||
public void clearSavedRequest(HttpSession session) {
|
||||
session.removeAttribute(REDIRECT_URI);
|
||||
session.removeAttribute(SAVED_METHOD);
|
||||
session.removeAttribute(SAVED_HEADERS);
|
||||
session.removeAttribute(SAVED_BODY);
|
||||
}
|
||||
|
||||
public void servletRequestLogout() {
|
||||
|
||||
}
|
||||
|
||||
public static String getCharsetFromContentType(String contentType) {
|
||||
|
||||
if (contentType == null)
|
||||
return (null);
|
||||
int start = contentType.indexOf("charset=");
|
||||
if (start < 0)
|
||||
return (null);
|
||||
String encoding = contentType.substring(start + 8);
|
||||
int end = encoding.indexOf(';');
|
||||
if (end >= 0)
|
||||
encoding = encoding.substring(0, end);
|
||||
encoding = encoding.trim();
|
||||
if ((encoding.length() > 2) && (encoding.startsWith("\""))
|
||||
&& (encoding.endsWith("\"")))
|
||||
encoding = encoding.substring(1, encoding.length() - 1);
|
||||
return (encoding.trim());
|
||||
|
||||
}
|
||||
|
||||
|
||||
public HttpServletRequestWrapper buildWrapper(HttpSession session, final KeycloakAccount account) {
|
||||
if (needRequestRestore) {
|
||||
final String method = (String)session.getAttribute(SAVED_METHOD);
|
||||
final byte[] body = (byte[])session.getAttribute(SAVED_BODY);
|
||||
final MultivaluedHashMap<String, String> headers = (MultivaluedHashMap<String, String>)session.getAttribute(SAVED_HEADERS);
|
||||
clearSavedRequest(session);
|
||||
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) {
|
||||
protected MultivaluedHashMap<String, String> parameters;
|
||||
|
||||
MultivaluedHashMap<String, String> getParams() {
|
||||
if (parameters != null) return parameters;
|
||||
|
||||
if (body == null) return new MultivaluedHashMap<String, String>();
|
||||
|
||||
String contentType = getContentType();
|
||||
if (contentType != null && contentType.toLowerCase().startsWith("application/x-www-form-urlencoded")) {
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(body);
|
||||
try {
|
||||
parameters = parseForm(is);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return parameters;
|
||||
|
||||
}
|
||||
@Override
|
||||
public boolean isUserInRole(String role) {
|
||||
return account.getRoles().contains(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return account.getPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
if (needRequestRestore) {
|
||||
return method;
|
||||
} else {
|
||||
return super.getMethod();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String name) {
|
||||
if (needRequestRestore && headers != null) {
|
||||
return headers.getFirst(name.toLowerCase());
|
||||
}
|
||||
return super.getHeader(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getHeaders(String name) {
|
||||
if (needRequestRestore && headers != null) {
|
||||
List<String> values = headers.getList(name.toLowerCase());
|
||||
if (values == null) return Collections.emptyEnumeration();
|
||||
else return Collections.enumeration(values);
|
||||
}
|
||||
return super.getHeaders(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getHeaderNames() {
|
||||
if (needRequestRestore && headers != null) {
|
||||
return Collections.enumeration(headers.keySet());
|
||||
}
|
||||
return super.getHeaderNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
|
||||
if (needRequestRestore && body != null) {
|
||||
final ByteArrayInputStream is = new ByteArrayInputStream(body);
|
||||
return new ServletInputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return is.read();
|
||||
}
|
||||
};
|
||||
}
|
||||
return super.getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout() throws ServletException {
|
||||
servletRequestLogout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDateHeader(String name) {
|
||||
if (!needRequestRestore) return super.getDateHeader(name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntHeader(String name) {
|
||||
if (!needRequestRestore) return super.getIntHeader(name);
|
||||
String value = getHeader(name);
|
||||
if (value == null) return -1;
|
||||
return Integer.valueOf(value);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String name) {
|
||||
if (!needRequestRestore) return super.getParameterValues(name);
|
||||
MultivaluedHashMap<String, String> formParams = getParams();
|
||||
if (formParams == null) {
|
||||
return super.getParameterValues(name);
|
||||
}
|
||||
String[] values = request.getParameterValues(name);
|
||||
List<String> list = new LinkedList<>();
|
||||
if (values != null) {
|
||||
for (String val : values) list.add(val);
|
||||
}
|
||||
List<String> vals = formParams.get(name);
|
||||
if (vals != null) list.addAll(vals);
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getParameterNames() {
|
||||
if (!needRequestRestore) return super.getParameterNames();
|
||||
MultivaluedHashMap<String, String> formParams = getParams();
|
||||
if (formParams == null) {
|
||||
return super.getParameterNames();
|
||||
}
|
||||
Set<String> names = new HashSet<>();
|
||||
Enumeration<String> qnames = super.getParameterNames();
|
||||
while (qnames.hasMoreElements()) names.add(qnames.nextElement());
|
||||
names.addAll(formParams.keySet());
|
||||
return Collections.enumeration(names);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
if (!needRequestRestore) return super.getParameterMap();
|
||||
MultivaluedHashMap<String, String> formParams = getParams();
|
||||
if (formParams == null) {
|
||||
return super.getParameterMap();
|
||||
}
|
||||
Map<String, String[]> map = new HashMap<>();
|
||||
Enumeration<String> names = getParameterNames();
|
||||
while (names.hasMoreElements()) {
|
||||
String name = names.nextElement();
|
||||
String[] values = getParameterValues(name);
|
||||
if (values != null) {
|
||||
map.put(name, values);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String name) {
|
||||
if (!needRequestRestore) return super.getParameter(name);
|
||||
String param = super.getParameter(name);
|
||||
if (param != null) return param;
|
||||
MultivaluedHashMap<String, String> formParams = getParams();
|
||||
if (formParams == null) {
|
||||
return null;
|
||||
}
|
||||
return formParams.getFirst(name);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() throws IOException {
|
||||
if (!needRequestRestore) return super.getReader();
|
||||
return new BufferedReader(new InputStreamReader(getInputStream()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentLength() {
|
||||
if (!needRequestRestore) return super.getContentLength();
|
||||
String header = getHeader("content-length");
|
||||
if (header == null) return -1;
|
||||
return Integer.valueOf(header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
if (!needRequestRestore) return super.getContentType();
|
||||
return getHeader("content-type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacterEncoding() {
|
||||
if (!needRequestRestore) return super.getCharacterEncoding();
|
||||
return getCharsetFromContentType(getContentType());
|
||||
}
|
||||
|
||||
};
|
||||
return wrapper;
|
||||
} else {
|
||||
return new HttpServletRequestWrapper(request) {
|
||||
@Override
|
||||
public boolean isUserInRole(String role) {
|
||||
return account.getRoles().contains(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
if (account == null) return null;
|
||||
return account.getPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout() throws ServletException {
|
||||
servletRequestLogout();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public String getRedirectUri() {
|
||||
HttpSession session = request.getSession(true);
|
||||
return (String)session.getAttribute(REDIRECT_URI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreRequest() {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session == null) return false;
|
||||
return session.getAttribute(REDIRECT_URI) != null;
|
||||
}
|
||||
|
||||
public static MultivaluedHashMap<String, String> parseForm(InputStream entityStream)
|
||||
throws IOException
|
||||
{
|
||||
char[] buffer = new char[100];
|
||||
StringBuffer buf = new StringBuffer();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(entityStream));
|
||||
|
||||
int wasRead = 0;
|
||||
do
|
||||
{
|
||||
wasRead = reader.read(buffer, 0, 100);
|
||||
if (wasRead > 0) buf.append(buffer, 0, wasRead);
|
||||
} while (wasRead > -1);
|
||||
|
||||
String form = buf.toString();
|
||||
|
||||
MultivaluedHashMap<String, String> formData = new MultivaluedHashMap<String, String>();
|
||||
if ("".equals(form)) return formData;
|
||||
|
||||
String[] params = form.split("&");
|
||||
|
||||
for (String param : params)
|
||||
{
|
||||
if (param.indexOf('=') >= 0)
|
||||
{
|
||||
String[] nv = param.split("=");
|
||||
String val = nv.length > 1 ? nv[1] : "";
|
||||
formData.add(Encode.decode(nv[0]), Encode.decode(val));
|
||||
}
|
||||
else
|
||||
{
|
||||
formData.add(Encode.decode(param), "");
|
||||
}
|
||||
}
|
||||
return formData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void saveRequest() {
|
||||
HttpSession session = request.getSession(true);
|
||||
session.setAttribute(REDIRECT_URI, facade.getRequest().getURI());
|
||||
session.setAttribute(SAVED_METHOD, request.getMethod());
|
||||
MultivaluedHashMap<String, String> headers = new MultivaluedHashMap<>();
|
||||
Enumeration<String> names = request.getHeaderNames();
|
||||
while (names.hasMoreElements()) {
|
||||
String name = names.nextElement();
|
||||
Enumeration<String> values = request.getHeaders(name);
|
||||
while (values.hasMoreElements()) {
|
||||
headers.add(name.toLowerCase(), values.nextElement());
|
||||
}
|
||||
}
|
||||
session.setAttribute(SAVED_HEADERS, headers);
|
||||
if (request.getMethod().equalsIgnoreCase("GET")) {
|
||||
return;
|
||||
}
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
int totalRead = 0;
|
||||
try {
|
||||
InputStream is = request.getInputStream();
|
||||
|
||||
while ( (bytesRead = is.read(buffer) ) >= 0) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
totalRead += bytesRead;
|
||||
if (totalRead > maxBuffer) {
|
||||
throw new RuntimeException("max buffer reached on a saved request");
|
||||
}
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
byte[] body = os.toByteArray();
|
||||
// Only save the request body if there is something to save
|
||||
if (body.length > 0) {
|
||||
session.setAttribute(SAVED_BODY, body);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,268 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.servlet;
|
||||
|
||||
import org.keycloak.adapters.spi.AuthenticationError;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.spi.LogoutError;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.common.util.ServerCookie;
|
||||
import org.keycloak.common.util.UriUtils;
|
||||
|
||||
import javax.security.cert.X509Certificate;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ServletHttpFacade implements HttpFacade {
|
||||
protected final RequestFacade requestFacade = new RequestFacade();
|
||||
protected final ResponseFacade responseFacade = new ResponseFacade();
|
||||
protected HttpServletRequest request;
|
||||
protected HttpServletResponse response;
|
||||
protected MultivaluedHashMap<String, String> queryParameters;
|
||||
|
||||
public ServletHttpFacade(HttpServletRequest request, HttpServletResponse response) {
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
protected class RequestFacade implements Request {
|
||||
|
||||
private InputStream inputStream;
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return request.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getURI() {
|
||||
StringBuffer buf = request.getRequestURL();
|
||||
if (request.getQueryString() != null) {
|
||||
buf.append('?').append(request.getQueryString());
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRelativePath() {
|
||||
String uri = request.getRequestURI();
|
||||
String contextPath = request.getContextPath();
|
||||
String servletPath = uri.substring(uri.indexOf(contextPath) + contextPath.length());
|
||||
|
||||
if ("".equals(servletPath)) {
|
||||
servletPath = "/";
|
||||
}
|
||||
|
||||
return servletPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return request.isSecure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstParam(String param) {
|
||||
return request.getParameter(param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParamValue(String param) {
|
||||
if (queryParameters == null) {
|
||||
queryParameters = UriUtils.decodeQueryString(request.getQueryString());
|
||||
}
|
||||
return queryParameters.getFirst(param);
|
||||
}
|
||||
|
||||
public MultivaluedHashMap<String, String> getQueryParameters() {
|
||||
if (queryParameters == null) {
|
||||
queryParameters = UriUtils.decodeQueryString(request.getQueryString());
|
||||
}
|
||||
return queryParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cookie getCookie(String cookieName) {
|
||||
if (request.getCookies() == null) return null;
|
||||
javax.servlet.http.Cookie cookie = null;
|
||||
for (javax.servlet.http.Cookie c : request.getCookies()) {
|
||||
if (c.getName().equals(cookieName)) {
|
||||
cookie = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cookie == null) return null;
|
||||
return new Cookie(cookie.getName(), cookie.getValue(), cookie.getVersion(), cookie.getDomain(), cookie.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String name) {
|
||||
return request.getHeader(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getHeaders(String name) {
|
||||
Enumeration<String> values = request.getHeaders(name);
|
||||
List<String> list = new LinkedList<>();
|
||||
while (values.hasMoreElements()) list.add(values.nextElement());
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return getInputStream(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream(boolean buffered) {
|
||||
if (inputStream != null) {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
if (buffered) {
|
||||
try {
|
||||
return inputStream = new BufferedInputStream(request.getInputStream());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return request.getInputStream();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteAddr() {
|
||||
return request.getRemoteAddr();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setError(AuthenticationError error) {
|
||||
request.setAttribute(AuthenticationError.class.getName(), error);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setError(LogoutError error) {
|
||||
request.setAttribute(LogoutError.class.getName(), error);
|
||||
}
|
||||
}
|
||||
public boolean isEnded() {
|
||||
return responseFacade.isEnded();
|
||||
}
|
||||
|
||||
protected class ResponseFacade implements Response {
|
||||
protected boolean ended;
|
||||
|
||||
@Override
|
||||
public void setStatus(int status) {
|
||||
response.setStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String name, String value) {
|
||||
response.addHeader(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String name, String value) {
|
||||
response.setHeader(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetCookie(String name, String path) {
|
||||
setCookie(name, "", path, null, 0, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly) {
|
||||
StringBuilder cookieBuf = new StringBuilder();
|
||||
ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, null, maxAge, secure, httpOnly, null);
|
||||
String cookie = cookieBuf.toString();
|
||||
response.addHeader("Set-Cookie", cookie);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() {
|
||||
try {
|
||||
return response.getOutputStream();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int code) {
|
||||
try {
|
||||
response.sendError(code);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int code, String message) {
|
||||
try {
|
||||
response.sendError(code, message);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
ended = true;
|
||||
}
|
||||
|
||||
public boolean isEnded() {
|
||||
return ended;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Request getRequest() {
|
||||
return requestFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getResponse() {
|
||||
return responseFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain() {
|
||||
throw new IllegalStateException("Not supported yet");
|
||||
}
|
||||
}
|
15
pom.xml
15
pom.xml
|
@ -1003,16 +1003,6 @@
|
|||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-servlet-adapter-spi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-jakarta-servlet-adapter-spi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
@ -1063,11 +1053,6 @@
|
|||
<artifactId>keycloak-js-adapter-jar</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-jakarta-servlet-filter-adapter</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-as7-adapter</artifactId>
|
||||
|
|
Loading…
Reference in a new issue