Introduce CMS Servlet.
authorMathieu Baudier <mbaudier@argeo.org>
Sat, 1 Jan 2022 08:58:34 +0000 (09:58 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Sat, 1 Jan 2022 08:58:34 +0000 (09:58 +0100)
45 files changed:
dep/org.argeo.dep.cms.node/pom.xml
org.argeo.cms.servlet/.classpath [new file with mode: 0644]
org.argeo.cms.servlet/.project [new file with mode: 0644]
org.argeo.cms.servlet/OSGI-INF/pkgServlet.xml [new file with mode: 0644]
org.argeo.cms.servlet/OSGI-INF/pkgServletContext.xml [new file with mode: 0644]
org.argeo.cms.servlet/bnd.bnd [new file with mode: 0644]
org.argeo.cms.servlet/build.properties [new file with mode: 0644]
org.argeo.cms.servlet/pom.xml [new file with mode: 0644]
org.argeo.cms.servlet/src/org/argeo/cms/servlet/CmsServletContext.java [new file with mode: 0644]
org.argeo.cms.servlet/src/org/argeo/cms/servlet/PrivateWwwAuthServletContext.java [new file with mode: 0644]
org.argeo.cms.servlet/src/org/argeo/cms/servlet/ServletAuthUtils.java [new file with mode: 0644]
org.argeo.cms.servlet/src/org/argeo/cms/servlet/ServletHttpRequest.java [new file with mode: 0644]
org.argeo.cms.servlet/src/org/argeo/cms/servlet/ServletHttpResponse.java [new file with mode: 0644]
org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/HttpUtils.java [new file with mode: 0644]
org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/PkgServlet.java [new file with mode: 0644]
org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/RobotServlet.java [new file with mode: 0644]
org.argeo.cms.swt/pom.xml
org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java
org.argeo.cms.ui.rap/src/org/argeo/cms/web/AbstractCmsEntryPoint.java
org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebEntryPoint.java
org.argeo.cms/OSGI-INF/pkgServlet.xml [deleted file]
org.argeo.cms/OSGI-INF/pkgServletContext.xml [deleted file]
org.argeo.cms/bnd.bnd
org.argeo.cms/src/org/argeo/cms/auth/AnonymousLoginModule.java
org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java
org.argeo.cms/src/org/argeo/cms/auth/HttpRequest.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallback.java
org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallbackHandler.java
org.argeo.cms/src/org/argeo/cms/auth/HttpResponse.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/auth/HttpSession.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java
org.argeo.cms/src/org/argeo/cms/auth/IdentLoginModule.java
org.argeo.cms/src/org/argeo/cms/auth/SingleUserLoginModule.java
org.argeo.cms/src/org/argeo/cms/auth/SpnegoLoginModule.java
org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java
org.argeo.cms/src/org/argeo/cms/internal/auth/CmsUserManagerImpl.java
org.argeo.cms/src/org/argeo/cms/internal/http/HttpUtils.java [deleted file]
org.argeo.cms/src/org/argeo/cms/internal/http/PkgServlet.java [deleted file]
org.argeo.cms/src/org/argeo/cms/internal/http/RobotServlet.java [deleted file]
org.argeo.cms/src/org/argeo/cms/internal/http/WebCmsSessionImpl.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java
org.argeo.cms/src/org/argeo/cms/servlet/CmsServletContext.java [deleted file]
org.argeo.cms/src/org/argeo/cms/servlet/PrivateWwwAuthServletContext.java [deleted file]
org.argeo.cms/src/org/argeo/cms/servlet/ServletAuthUtils.java [deleted file]
pom.xml

index 3348ecd701a30f5ab6e49a0882b6f0072ad83787..7f1ca14ce68fa128d6be3f8f38f5fd71e6489bd6 100644 (file)
                </dependency>
 
                <!-- Argeo Commons -->
+               <dependency>
+                       <groupId>org.argeo.commons</groupId>
+                       <artifactId>org.argeo.cms.servlet</artifactId>
+                       <version>2.3-SNAPSHOT</version>
+               </dependency>
                <dependency>
                        <groupId>org.argeo.commons</groupId>
                        <artifactId>org.argeo.cms.jcr</artifactId>
diff --git a/org.argeo.cms.servlet/.classpath b/org.argeo.cms.servlet/.classpath
new file mode 100644 (file)
index 0000000..e801ebf
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.argeo.cms.servlet/.project b/org.argeo.cms.servlet/.project
new file mode 100644 (file)
index 0000000..b1a25fc
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.argeo.cms.servlet</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/org.argeo.cms.servlet/OSGI-INF/pkgServlet.xml b/org.argeo.cms.servlet/OSGI-INF/pkgServlet.xml
new file mode 100644 (file)
index 0000000..30e5231
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.argeo.cms.pkgServlet">
+   <implementation class="org.argeo.cms.internal.http.PkgServlet"/>
+   <service>
+      <provide interface="javax.servlet.Servlet"/>
+   </service>
+   <property name="osgi.http.whiteboard.servlet.pattern" type="String" value="/*"/>
+   <property name="osgi.http.whiteboard.context.select" type="String" value="(osgi.http.whiteboard.context.name=pkgServletContext)"/>
+</scr:component>
diff --git a/org.argeo.cms.servlet/OSGI-INF/pkgServletContext.xml b/org.argeo.cms.servlet/OSGI-INF/pkgServletContext.xml
new file mode 100644 (file)
index 0000000..7540a2c
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" name="org.argeo.cms.pkgServletContext">
+   <implementation class="org.argeo.cms.servlet.CmsServletContext"/>
+   <service>
+      <provide interface="org.osgi.service.http.context.ServletContextHelper"/>
+   </service>
+   <property name="osgi.http.whiteboard.context.name" type="String" value="pkgServletContext"/>
+   <property name="osgi.http.whiteboard.context.path" type="String" value="/pkg"/>
+</scr:component>
diff --git a/org.argeo.cms.servlet/bnd.bnd b/org.argeo.cms.servlet/bnd.bnd
new file mode 100644 (file)
index 0000000..c8251a7
--- /dev/null
@@ -0,0 +1,10 @@
+Import-Package:\
+org.osgi.service.http;version=0.0.0,\
+org.osgi.service.http.whiteboard;version=0.0.0,\
+org.osgi.framework.namespace;version=0.0.0,\
+org.argeo.api,\
+*
+
+Service-Component:\
+OSGI-INF/pkgServletContext.xml,\
+OSGI-INF/pkgServlet.xml
diff --git a/org.argeo.cms.servlet/build.properties b/org.argeo.cms.servlet/build.properties
new file mode 100644 (file)
index 0000000..34d2e4d
--- /dev/null
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
diff --git a/org.argeo.cms.servlet/pom.xml b/org.argeo.cms.servlet/pom.xml
new file mode 100644 (file)
index 0000000..a60b42d
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.argeo.commons</groupId>
+               <version>2.3-SNAPSHOT</version>
+               <artifactId>argeo-commons</artifactId>
+               <relativePath>..</relativePath>
+       </parent>
+       <artifactId>org.argeo.cms.servlet</artifactId>
+       <packaging>jar</packaging>
+       <name>CMS Servlet</name>
+       <description>CMS components depending on the Servlet APIs</description>
+       <dependencies>
+               <dependency>
+                       <groupId>org.argeo.commons</groupId>
+                       <artifactId>org.argeo.cms</artifactId>
+                       <version>2.3-SNAPSHOT</version>
+               </dependency>
+       </dependencies>
+</project>
\ No newline at end of file
diff --git a/org.argeo.cms.servlet/src/org/argeo/cms/servlet/CmsServletContext.java b/org.argeo.cms.servlet/src/org/argeo/cms/servlet/CmsServletContext.java
new file mode 100644 (file)
index 0000000..ff341a2
--- /dev/null
@@ -0,0 +1,96 @@
+package org.argeo.cms.servlet;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.PrivilegedAction;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.api.NodeConstants;
+import org.argeo.cms.auth.HttpRequestCallbackHandler;
+import org.argeo.cms.servlet.internal.HttpUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.service.http.context.ServletContextHelper;
+
+/**
+ * Default servlet context degrading to anonymous if the the session is not
+ * pre-authenticated.
+ */
+public class CmsServletContext extends ServletContextHelper {
+       private final static Log log = LogFactory.getLog(CmsServletContext.class);
+       // use CMS bundle for resources
+       private Bundle bundle = FrameworkUtil.getBundle(getClass());
+
+       public void init(Map<String, String> properties) {
+
+       }
+
+       public void destroy() {
+
+       }
+
+       @Override
+       public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException {
+               if (log.isTraceEnabled())
+                       HttpUtils.logRequestHeaders(log, request);
+               LoginContext lc;
+               try {
+                       lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
+                                       new HttpRequestCallbackHandler(new ServletHttpRequest(request), new ServletHttpResponse(response)));
+                       lc.login();
+               } catch (LoginException e) {
+                       lc = processUnauthorized(request, response);
+                       if (log.isTraceEnabled())
+                               HttpUtils.logResponseHeaders(log, response);
+                       if (lc == null)
+                               return false;
+               }
+
+               Subject subject = lc.getSubject();
+               // log.debug("SERVLET CONTEXT: "+subject);
+               Subject.doAs(subject, new PrivilegedAction<Void>() {
+
+                       @Override
+                       public Void run() {
+                               // TODO also set login context in order to log out ?
+                               ServletAuthUtils.configureRequestSecurity(request);
+                               return null;
+                       }
+
+               });
+               return true;
+       }
+
+       @Override
+       public void finishSecurity(HttpServletRequest request, HttpServletResponse response) {
+               ServletAuthUtils.clearRequestSecurity(request);
+       }
+
+       protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) {
+               // anonymous
+               try {
+                       LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS,
+                                       new HttpRequestCallbackHandler(new ServletHttpRequest(request), new ServletHttpResponse(response)));
+                       lc.login();
+                       return lc;
+               } catch (LoginException e1) {
+                       if (log.isDebugEnabled())
+                               log.error("Cannot log in as anonymous", e1);
+                       return null;
+               }
+       }
+
+       @Override
+       public URL getResource(String name) {
+               return bundle.getResource(name);
+       }
+
+}
diff --git a/org.argeo.cms.servlet/src/org/argeo/cms/servlet/PrivateWwwAuthServletContext.java b/org.argeo.cms.servlet/src/org/argeo/cms/servlet/PrivateWwwAuthServletContext.java
new file mode 100644 (file)
index 0000000..3bea0b4
--- /dev/null
@@ -0,0 +1,39 @@
+package org.argeo.cms.servlet;
+
+import javax.security.auth.login.LoginContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.argeo.cms.auth.SpnegoLoginModule;
+import org.argeo.cms.servlet.internal.HttpUtils;
+
+/** Servlet context forcing authentication. */
+public class PrivateWwwAuthServletContext extends CmsServletContext {
+       // TODO make it configurable
+       private final String httpAuthRealm = "Argeo";
+       private final boolean forceBasic = false;
+
+       @Override
+       protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) {
+               askForWwwAuth(request, response);
+               return null;
+       }
+
+       protected void askForWwwAuth(HttpServletRequest request, HttpServletResponse response) {
+               // response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic
+               // realm=\"" + httpAuthRealm + "\"");
+               if (SpnegoLoginModule.hasAcceptorCredentials() && !forceBasic)// SPNEGO
+                       response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "Negotiate");
+               else
+                       response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "Basic realm=\"" + httpAuthRealm + "\"");
+
+               // response.setDateHeader("Date", System.currentTimeMillis());
+               // response.setDateHeader("Expires", System.currentTimeMillis() + (24 *
+               // 60 * 60 * 1000));
+               // response.setHeader("Accept-Ranges", "bytes");
+               // response.setHeader("Connection", "Keep-Alive");
+               // response.setHeader("Keep-Alive", "timeout=5, max=97");
+               // response.setContentType("text/html; charset=UTF-8");
+               response.setStatus(401);
+       }
+}
diff --git a/org.argeo.cms.servlet/src/org/argeo/cms/servlet/ServletAuthUtils.java b/org.argeo.cms.servlet/src/org/argeo/cms/servlet/ServletAuthUtils.java
new file mode 100644 (file)
index 0000000..67db467
--- /dev/null
@@ -0,0 +1,66 @@
+package org.argeo.cms.servlet;
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.function.Supplier;
+
+import javax.security.auth.Subject;
+import javax.servlet.http.HttpServletRequest;
+
+import org.argeo.api.cms.CmsSession;
+import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.osgi.CmsOsgiUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.service.http.HttpContext;
+
+/** Authentications utilities when using servlets. */
+public class ServletAuthUtils {
+       private static BundleContext bundleContext = FrameworkUtil.getBundle(ServletAuthUtils.class).getBundleContext();
+
+       /**
+        * Execute this supplier, using the CMS class loader as context classloader.
+        * Useful to log in to JCR.
+        */
+       public final static <T> T doAs(Supplier<T> supplier, HttpServletRequest req) {
+               ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
+               Thread.currentThread().setContextClassLoader(ServletAuthUtils.class.getClassLoader());
+               try {
+                       return Subject.doAs(
+                                       Subject.getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName())),
+                                       new PrivilegedAction<T>() {
+
+                                               @Override
+                                               public T run() {
+                                                       return supplier.get();
+                                               }
+
+                                       });
+               } finally {
+                       Thread.currentThread().setContextClassLoader(currentContextCl);
+               }
+       }
+
+       public final static void configureRequestSecurity(HttpServletRequest req) {
+               if (req.getAttribute(AccessControlContext.class.getName()) != null)
+                       throw new IllegalStateException("Request already authenticated.");
+               AccessControlContext acc = AccessController.getContext();
+               req.setAttribute(HttpContext.REMOTE_USER, CurrentUser.getUsername());
+               req.setAttribute(AccessControlContext.class.getName(), acc);
+       }
+
+       public final static void clearRequestSecurity(HttpServletRequest req) {
+               if (req.getAttribute(AccessControlContext.class.getName()) == null)
+                       throw new IllegalStateException("Cannot clear non-authenticated request.");
+               req.setAttribute(HttpContext.REMOTE_USER, null);
+               req.setAttribute(AccessControlContext.class.getName(), null);
+       }
+
+       public static CmsSession getCmsSession(HttpServletRequest req) {
+               Subject subject = Subject
+                               .getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName()));
+               CmsSession cmsSession = CmsOsgiUtils.getCmsSession(bundleContext, subject);
+               return cmsSession;
+       }
+}
diff --git a/org.argeo.cms.servlet/src/org/argeo/cms/servlet/ServletHttpRequest.java b/org.argeo.cms.servlet/src/org/argeo/cms/servlet/ServletHttpRequest.java
new file mode 100644 (file)
index 0000000..523f7b7
--- /dev/null
@@ -0,0 +1,83 @@
+package org.argeo.cms.servlet;
+
+import java.util.Locale;
+import java.util.Objects;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.argeo.cms.auth.HttpRequest;
+import org.argeo.cms.auth.HttpSession;
+
+public class ServletHttpRequest implements HttpRequest {
+       private final HttpServletRequest request;
+
+       public ServletHttpRequest(HttpServletRequest request) {
+               Objects.requireNonNull(request);
+               this.request = request;
+       }
+
+       @Override
+       public HttpSession getSession() {
+               return new ServletHttpSession();
+       }
+
+       @Override
+       public HttpSession createSession() {
+               request.getSession(true);
+               return new ServletHttpSession();
+       }
+
+       @Override
+       public Locale getLocale() {
+               return request.getLocale();
+       }
+
+       @Override
+       public Object getAttribute(String key) {
+               return request.getAttribute(key);
+       }
+
+       @Override
+       public void setAttribute(String key, Object object) {
+               request.setAttribute(key, object);
+       }
+
+       @Override
+       public String getHeader(String key) {
+               return request.getHeader(key);
+       }
+
+       @Override
+       public String getRemoteAddr() {
+               return request.getRemoteAddr();
+       }
+
+       @Override
+       public int getLocalPort() {
+               return request.getLocalPort();
+       }
+
+       @Override
+       public int getRemotePort() {
+               return request.getRemotePort();
+       }
+
+       private class ServletHttpSession implements HttpSession {
+
+               @Override
+               public boolean isValid() {
+                       try {// test http session
+                               request.getSession(false).getCreationTime();
+                               return true;
+                       } catch (IllegalStateException ise) {
+                               return false;
+                       }
+               }
+
+               @Override
+               public String getId() {
+                       return request.getSession(false).getId();
+               }
+
+       }
+}
diff --git a/org.argeo.cms.servlet/src/org/argeo/cms/servlet/ServletHttpResponse.java b/org.argeo.cms.servlet/src/org/argeo/cms/servlet/ServletHttpResponse.java
new file mode 100644 (file)
index 0000000..6cbe2c4
--- /dev/null
@@ -0,0 +1,22 @@
+package org.argeo.cms.servlet;
+
+import java.util.Objects;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.argeo.cms.auth.HttpResponse;
+
+public class ServletHttpResponse implements HttpResponse {
+       private final HttpServletResponse response;
+
+       public ServletHttpResponse(HttpServletResponse response) {
+               Objects.requireNonNull(response);
+               this.response = response;
+       }
+
+       @Override
+       public void setHeader(String keys, String value) {
+               response.setHeader(keys, value);
+       }
+
+}
diff --git a/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/HttpUtils.java b/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/HttpUtils.java
new file mode 100644 (file)
index 0000000..5f8c8c5
--- /dev/null
@@ -0,0 +1,70 @@
+package org.argeo.cms.servlet.internal;
+
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+
+public class HttpUtils {
+       public final static String HEADER_AUTHORIZATION = "Authorization";
+       public final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
+
+       static boolean isBrowser(String userAgent) {
+               return userAgent.contains("webkit") || userAgent.contains("gecko") || userAgent.contains("firefox")
+                               || userAgent.contains("msie") || userAgent.contains("chrome") || userAgent.contains("chromium")
+                               || userAgent.contains("opera") || userAgent.contains("browser");
+       }
+
+       public static void logResponseHeaders(Log log, HttpServletResponse response) {
+               if (!log.isDebugEnabled())
+                       return;
+               for (String headerName : response.getHeaderNames()) {
+                       Object headerValue = response.getHeader(headerName);
+                       log.debug(headerName + ": " + headerValue);
+               }
+       }
+
+       public static void logRequestHeaders(Log log, HttpServletRequest request) {
+               if (!log.isDebugEnabled())
+                       return;
+               for (Enumeration<String> headerNames = request.getHeaderNames(); headerNames.hasMoreElements();) {
+                       String headerName = headerNames.nextElement();
+                       Object headerValue = request.getHeader(headerName);
+                       log.debug(headerName + ": " + headerValue);
+               }
+               log.debug(request.getRequestURI() + "\n");
+       }
+
+       public static void logRequest(Log log, HttpServletRequest request) {
+               log.debug("contextPath=" + request.getContextPath());
+               log.debug("servletPath=" + request.getServletPath());
+               log.debug("requestURI=" + request.getRequestURI());
+               log.debug("queryString=" + request.getQueryString());
+               StringBuilder buf = new StringBuilder();
+               // headers
+               Enumeration<String> en = request.getHeaderNames();
+               while (en.hasMoreElements()) {
+                       String header = en.nextElement();
+                       Enumeration<String> values = request.getHeaders(header);
+                       while (values.hasMoreElements())
+                               buf.append("  " + header + ": " + values.nextElement());
+                       buf.append('\n');
+               }
+
+               // attributed
+               Enumeration<String> an = request.getAttributeNames();
+               while (an.hasMoreElements()) {
+                       String attr = an.nextElement();
+                       Object value = request.getAttribute(attr);
+                       buf.append("  " + attr + ": " + value);
+                       buf.append('\n');
+               }
+               log.debug("\n" + buf);
+       }
+
+       private HttpUtils() {
+
+       }
+}
diff --git a/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/PkgServlet.java b/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/PkgServlet.java
new file mode 100644 (file)
index 0000000..c762b67
--- /dev/null
@@ -0,0 +1,133 @@
+package org.argeo.cms.servlet.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collection;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.IOUtils;
+import org.argeo.cms.osgi.PublishNamespace;
+import org.argeo.osgi.util.FilterRequirement;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.Version;
+import org.osgi.framework.VersionRange;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.framework.wiring.FrameworkWiring;
+import org.osgi.resource.Requirement;
+
+public class PkgServlet extends HttpServlet {
+       private static final long serialVersionUID = 7660824185145214324L;
+
+       private BundleContext bundleContext = FrameworkUtil.getBundle(PkgServlet.class).getBundleContext();
+
+       @Override
+       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+               String pathInfo = req.getPathInfo();
+
+               String pkg, versionStr, file;
+               String[] parts = pathInfo.split("/");
+               // first is always empty
+               if (parts.length == 4) {
+                       pkg = parts[1];
+                       versionStr = parts[2];
+                       file = parts[3];
+               } else if (parts.length == 3) {
+                       pkg = parts[1];
+                       versionStr = null;
+                       file = parts[2];
+               } else {
+                       throw new IllegalArgumentException("Unsupported path length " + pathInfo);
+               }
+
+               FrameworkWiring frameworkWiring = bundleContext.getBundle(0).adapt(FrameworkWiring.class);
+               String filter;
+               if (versionStr == null) {
+                       filter = "(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")";
+               } else {
+                       if (versionStr.startsWith("[") || versionStr.startsWith("(")) {// range
+                               VersionRange versionRange = new VersionRange(versionStr);
+                               filter = "(&(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")"
+                                               + versionRange.toFilterString(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE) + ")";
+
+                       } else {
+                               Version version = new Version(versionStr);
+                               filter = "(&(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")("
+                                               + PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE + "=" + version + "))";
+                       }
+               }
+               Requirement requirement = new FilterRequirement(PackageNamespace.PACKAGE_NAMESPACE, filter);
+               Collection<BundleCapability> packages = frameworkWiring.findProviders(requirement);
+               if (packages.isEmpty()) {
+                       resp.sendError(404);
+                       return;
+               }
+
+               // TODO verify that it works with multiple versions
+               SortedMap<Version, BundleCapability> sorted = new TreeMap<>();
+               for (BundleCapability capability : packages) {
+                       sorted.put(capability.getRevision().getVersion(), capability);
+               }
+
+               Bundle bundle = sorted.get(sorted.firstKey()).getRevision().getBundle();
+               String entryPath = '/' + pkg.replace('.', '/') + '/' + file;
+               URL internalURL = bundle.getResource(entryPath);
+               if (internalURL == null) {
+                       resp.sendError(404);
+                       return;
+               }
+
+               // Resource found, we now check whether it can be published
+               boolean publish = false;
+               BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
+               capabilities: for (BundleCapability bundleCapability : bundleWiring
+                               .getCapabilities(PublishNamespace.CMS_PUBLISH_NAMESPACE)) {
+                       Object publishedPkg = bundleCapability.getAttributes().get(PublishNamespace.PKG);
+                       if (publishedPkg != null) {
+                               if (publishedPkg.equals("*") || publishedPkg.equals(pkg)) {
+                                       Object publishedFile = bundleCapability.getAttributes().get(PublishNamespace.FILE);
+                                       if (publishedFile == null) {
+                                               publish = true;
+                                               break capabilities;
+                                       } else {
+                                               String[] publishedFiles = publishedFile.toString().split(",");
+                                               for (String pattern : publishedFiles) {
+                                                       if (pattern.startsWith("*.")) {
+                                                               String ext = pattern.substring(1);
+                                                               if (file.endsWith(ext)) {
+                                                                       publish = true;
+                                                                       break capabilities;
+                                                               }
+                                                       } else {
+                                                               if (publishedFile.equals(file)) {
+                                                                       publish = true;
+                                                                       break capabilities;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               if (!publish) {
+                       resp.sendError(404);
+                       return;
+               }
+
+               try (InputStream in = internalURL.openStream()) {
+                       IOUtils.copy(in, resp.getOutputStream());
+               }
+       }
+
+}
diff --git a/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/RobotServlet.java b/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/RobotServlet.java
new file mode 100644 (file)
index 0000000..288ee26
--- /dev/null
@@ -0,0 +1,24 @@
+package org.argeo.cms.servlet.internal;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class RobotServlet extends HttpServlet {
+       private static final long serialVersionUID = 7935661175336419089L;
+
+       @Override
+       protected void service(HttpServletRequest request, HttpServletResponse response)
+                       throws ServletException, IOException {
+               PrintWriter writer = response.getWriter();
+               writer.append("User-agent: *\n");
+               writer.append("Disallow:\n");
+               response.setHeader("Content-Type", "text/plain");
+               writer.flush();
+       }
+
+}
index c6e772c89fe052505ff85f3d089a53090ee56b5d..b969259e71e8c7f3f17059e1495d4fd111fb3f26 100644 (file)
                        <artifactId>org.argeo.cms</artifactId>
                        <version>2.3-SNAPSHOT</version>
                </dependency>
+               <dependency>
+                       <groupId>org.argeo.commons</groupId>
+                       <artifactId>org.argeo.cms.servlet</artifactId>
+                       <version>2.3-SNAPSHOT</version>
+               </dependency>
 
                <!-- Specific -->
                <dependency>
index 8e12a8986e663be7ed8508c1e83953107d9002a2..e4d08d728e8fd5b9f5a39e79db403dce4bab5ed4 100644 (file)
@@ -16,7 +16,7 @@ import javax.security.auth.callback.PasswordCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
-import javax.servlet.http.HttpServletRequest;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.api.NodeConstants;
@@ -25,6 +25,8 @@ import org.argeo.api.cms.CmsView;
 import org.argeo.cms.CmsMsg;
 import org.argeo.cms.LocaleUtils;
 import org.argeo.cms.auth.HttpRequestCallback;
+import org.argeo.cms.servlet.ServletHttpRequest;
+import org.argeo.cms.servlet.ServletHttpResponse;
 import org.argeo.cms.swt.CmsStyles;
 import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.eclipse.ui.specific.UiContext;
@@ -309,8 +311,8 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
                        else if (callback instanceof PasswordCallback && passwordT != null)
                                ((PasswordCallback) callback).setPassword(passwordT.getTextChars());
                        else if (callback instanceof HttpRequestCallback) {
-                               ((HttpRequestCallback) callback).setRequest(UiContext.getHttpRequest());
-                               ((HttpRequestCallback) callback).setResponse(UiContext.getHttpResponse());
+                               ((HttpRequestCallback) callback).setRequest(new ServletHttpRequest(UiContext.getHttpRequest()));
+                               ((HttpRequestCallback) callback).setResponse(new ServletHttpResponse(UiContext.getHttpResponse()));
                        } else if (callback instanceof LanguageCallback) {
                                Locale toUse = null;
                                if (localeChoice != null)
index 504ed49786a21981c7b4b19c7d7f6dd8b6f28b37..c20068fa76b6925efb46e55ed628dc2ae7974c47 100644 (file)
@@ -29,6 +29,8 @@ import org.argeo.cms.CmsException;
 import org.argeo.cms.auth.CurrentUser;
 import org.argeo.cms.auth.HttpRequestCallback;
 import org.argeo.cms.auth.HttpRequestCallbackHandler;
+import org.argeo.cms.servlet.ServletHttpRequest;
+import org.argeo.cms.servlet.ServletHttpResponse;
 import org.argeo.cms.swt.CmsStyles;
 import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.eclipse.ui.specific.UiContext;
@@ -84,7 +86,8 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
                LoginContext lc;
                try {
                        lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
-                                       new HttpRequestCallbackHandler(UiContext.getHttpRequest(), UiContext.getHttpResponse()));
+                                       new HttpRequestCallbackHandler(new ServletHttpRequest(UiContext.getHttpRequest()),
+                                                       new ServletHttpResponse(UiContext.getHttpResponse())));
                        lc.login();
                } catch (LoginException e) {
                        try {
@@ -291,8 +294,10 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
                                                // handle HTTP context
                                                for (Callback callback : callbacks) {
                                                        if (callback instanceof HttpRequestCallback) {
-                                                               ((HttpRequestCallback) callback).setRequest(UiContext.getHttpRequest());
-                                                               ((HttpRequestCallback) callback).setResponse(UiContext.getHttpResponse());
+                                                               ((HttpRequestCallback) callback)
+                                                                               .setRequest(new ServletHttpRequest(UiContext.getHttpRequest()));
+                                                               ((HttpRequestCallback) callback)
+                                                                               .setResponse(new ServletHttpResponse(UiContext.getHttpResponse()));
                                                        }
                                                }
                                        }
index 4bdc5a0aa4fd554c2581767ba64d6658c9925c06..d7050e954d77784717e9393ed2d38ceb3f0cceec 100644 (file)
@@ -25,6 +25,8 @@ import org.argeo.cms.LocaleUtils;
 import org.argeo.cms.auth.CurrentUser;
 import org.argeo.cms.auth.HttpRequestCallbackHandler;
 import org.argeo.cms.osgi.CmsOsgiUtils;
+import org.argeo.cms.servlet.ServletHttpRequest;
+import org.argeo.cms.servlet.ServletHttpResponse;
 import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.swt.SimpleSwtUxContext;
 import org.argeo.cms.swt.dialogs.CmsFeedback;
@@ -84,7 +86,8 @@ public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationL
                LoginContext lc;
                try {
                        lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
-                                       new HttpRequestCallbackHandler(UiContext.getHttpRequest(), UiContext.getHttpResponse()));
+                                       new HttpRequestCallbackHandler(new ServletHttpRequest(UiContext.getHttpRequest()),
+                                                       new ServletHttpResponse(UiContext.getHttpResponse())));
                        lc.login();
                } catch (LoginException e) {
                        try {
diff --git a/org.argeo.cms/OSGI-INF/pkgServlet.xml b/org.argeo.cms/OSGI-INF/pkgServlet.xml
deleted file mode 100644 (file)
index 30e5231..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.argeo.cms.pkgServlet">
-   <implementation class="org.argeo.cms.internal.http.PkgServlet"/>
-   <service>
-      <provide interface="javax.servlet.Servlet"/>
-   </service>
-   <property name="osgi.http.whiteboard.servlet.pattern" type="String" value="/*"/>
-   <property name="osgi.http.whiteboard.context.select" type="String" value="(osgi.http.whiteboard.context.name=pkgServletContext)"/>
-</scr:component>
diff --git a/org.argeo.cms/OSGI-INF/pkgServletContext.xml b/org.argeo.cms/OSGI-INF/pkgServletContext.xml
deleted file mode 100644 (file)
index 7540a2c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" name="org.argeo.cms.pkgServletContext">
-   <implementation class="org.argeo.cms.servlet.CmsServletContext"/>
-   <service>
-      <provide interface="org.osgi.service.http.context.ServletContextHelper"/>
-   </service>
-   <property name="osgi.http.whiteboard.context.name" type="String" value="pkgServletContext"/>
-   <property name="osgi.http.whiteboard.context.path" type="String" value="/pkg"/>
-</scr:component>
index dc2cca306636f77ed379aa2e359d7130a7acfd01..61cb6cbab2914b5025be52a9b6c3f3cb44c61c42 100644 (file)
@@ -3,13 +3,8 @@ Bundle-Activator: org.argeo.cms.internal.kernel.Activator
 Import-Package: org.apache.commons.httpclient.cookie;resolution:=optional,\
 !com.sun.security.jgss,\
 org.osgi.*;version=0.0.0,\
-org.osgi.service.http.whiteboard;version=0.0.0,\
-org.osgi.framework.namespace;version=0.0.0,\
-org.apache.log4j.*;resolution:=optional,\
 *
 
-Service-Component:\
-OSGI-INF/cmsUserManager.xml,\
-OSGI-INF/pkgServletContext.xml,\
-OSGI-INF/pkgServlet.xml
+#Service-Component:\
+#OSGI-INF/cmsUserManager.xml,\
 
index 1d24be7ade914c45b4e862ca9fe310844c83cb3c..c5d067c0817bdf75a910d4a3dc92406a51923472 100644 (file)
@@ -7,7 +7,6 @@ import javax.security.auth.Subject;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
-import javax.servlet.http.HttpServletRequest;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -49,7 +48,7 @@ public class AnonymousLoginModule implements LoginModule {
        public boolean commit() throws LoginException {
                UserAdmin userAdmin = bc.getService(bc.getServiceReference(UserAdmin.class));
                Authorization authorization = userAdmin.getAuthorization(null);
-               HttpServletRequest request = (HttpServletRequest) sharedState.get(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST);
+               HttpRequest request = (HttpRequest) sharedState.get(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST);
                Locale locale = Locale.getDefault();
                if (request != null)
                        locale = request.getLocale();
index e854f5adfcd213bfbf31e2de2f97f3c44247727c..62888b15326ea72d52869923060bdf9626da01d6 100644 (file)
@@ -10,8 +10,6 @@ import javax.naming.InvalidNameException;
 import javax.naming.ldap.LdapName;
 import javax.security.auth.Subject;
 import javax.security.auth.x500.X500Principal;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
 
 import org.argeo.api.NodeConstants;
 import org.argeo.api.cms.CmsSession;
@@ -124,12 +122,12 @@ class CmsAuthUtils {
        }
 
        @SuppressWarnings("unused")
-       synchronized static void registerSessionAuthorization(HttpServletRequest request, Subject subject,
+       synchronized static void registerSessionAuthorization(HttpRequest request, Subject subject,
                        Authorization authorization, Locale locale) {
                // synchronized in order to avoid multiple registrations
                // TODO move it to a service in order to avoid static synchronization
                if (request != null) {
-                       HttpSession httpSession = request.getSession(false);
+                       HttpSession httpSession = request.getSession();
                        assert httpSession != null;
                        String httpSessId = httpSession.getId();
                        boolean anonymous = authorization.getName() == null;
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpRequest.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpRequest.java
new file mode 100644 (file)
index 0000000..4472255
--- /dev/null
@@ -0,0 +1,25 @@
+package org.argeo.cms.auth;
+
+import java.util.Locale;
+
+/** Transitional interface to decouple from the Servlet API. */
+public interface HttpRequest {
+       HttpSession getSession();
+
+       HttpSession createSession();
+
+       Locale getLocale();
+
+       Object getAttribute(String key);
+
+       void setAttribute(String key, Object object);
+
+       String getHeader(String key);
+
+       String getRemoteAddr();
+
+       int getLocalPort();
+
+       int getRemotePort();
+
+}
index 920f04e343514ecac54bd29697d2c87216959735..38e12c0c65a3340737963540953f8933d2a2d664 100644 (file)
@@ -1,29 +1,26 @@
 package org.argeo.cms.auth;
 
 import javax.security.auth.callback.Callback;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
 
 /** Retrieves credentials from an HTTP request. */
 public class HttpRequestCallback implements Callback {
-       private HttpServletRequest request;
-       private HttpServletResponse response;
+       private HttpRequest request;
+       private HttpResponse response;
        private HttpSession httpSession;
 
-       public HttpServletRequest getRequest() {
+       public HttpRequest getRequest() {
                return request;
        }
 
-       public void setRequest(HttpServletRequest request) {
+       public void setRequest(HttpRequest request) {
                this.request = request;
        }
 
-       public HttpServletResponse getResponse() {
+       public HttpResponse getResponse() {
                return response;
        }
 
-       public void setResponse(HttpServletResponse response) {
+       public void setResponse(HttpResponse response) {
                this.response = response;
        }
 
index df971e687f0c31bbd2eaf957a376be0c736a9c76..934fdd96bdf86ae7fa047507fc6c68acd3e58c25 100644 (file)
@@ -6,22 +6,19 @@ import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.LanguageCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
 
 /**
  * Callback handler populating {@link HttpRequestCallback}s with the provided
  * {@link HttpServletRequest}, and ignoring any other callback.
  */
 public class HttpRequestCallbackHandler implements CallbackHandler {
-       final private HttpServletRequest request;
-       final private HttpServletResponse response;
+       final private HttpRequest request;
+       final private HttpResponse response;
        final private HttpSession httpSession;
 
-       public HttpRequestCallbackHandler(HttpServletRequest request, HttpServletResponse response) {
+       public HttpRequestCallbackHandler(HttpRequest request, HttpResponse response) {
                this.request = request;
-               this.httpSession = request.getSession(false);
+               this.httpSession = request.getSession();
                this.response = response;
        }
 
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpResponse.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpResponse.java
new file mode 100644 (file)
index 0000000..67bad55
--- /dev/null
@@ -0,0 +1,7 @@
+package org.argeo.cms.auth;
+
+/** Transitional interface to decouple from the Servlet API. */
+public interface HttpResponse {
+       void setHeader(String keys, String value);
+
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpSession.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpSession.java
new file mode 100644 (file)
index 0000000..c7e52c1
--- /dev/null
@@ -0,0 +1,8 @@
+package org.argeo.cms.auth;
+
+/** Transitional interface to decouple from the Servlet API. */
+public interface HttpSession {
+       boolean isValid();
+
+       String getId();
+}
index c2dfead780ac8c9d71e2bbc932eafad00c15321e..8cc3941bc191b9b883306706f0d95f0ee8361fad 100644 (file)
@@ -13,9 +13,6 @@ import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -34,8 +31,8 @@ public class HttpSessionLoginModule implements LoginModule {
        private CallbackHandler callbackHandler = null;
        private Map<String, Object> sharedState = null;
 
-       private HttpServletRequest request = null;
-       private HttpServletResponse response = null;
+       private HttpRequest request = null;
+       private HttpResponse response = null;
 
        private BundleContext bc;
 
@@ -72,8 +69,8 @@ public class HttpSessionLoginModule implements LoginModule {
                                return false;
                        // TODO factorize with below
                        String httpSessionId = httpSession.getId();
-                       if (log.isTraceEnabled())
-                               log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId);
+//                     if (log.isTraceEnabled())
+//                             log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId);
                        CmsSessionImpl cmsSession = CmsAuthUtils.cmsSessionFromHttpSession(bc, httpSessionId);
                        if (cmsSession != null) {
                                authorization = cmsSession.getAuthorization();
@@ -84,16 +81,16 @@ public class HttpSessionLoginModule implements LoginModule {
                } else {
                        authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION);
                        if (authorization == null) {// search by session ID
-                               HttpSession httpSession = request.getSession(false);
+                               HttpSession httpSession = request.getSession();
                                if (httpSession == null) {
                                        // TODO make sure this is always safe
                                        if (log.isTraceEnabled())
                                                log.trace("Create http session");
-                                       httpSession = request.getSession(true);
+                                       httpSession = request.createSession();
                                }
                                String httpSessionId = httpSession.getId();
-                               if (log.isTraceEnabled())
-                                       log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId);
+//                             if (log.isTraceEnabled())
+//                                     log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId);
                                CmsSessionImpl cmsSession = CmsAuthUtils.cmsSessionFromHttpSession(bc, httpSessionId);
                                if (cmsSession != null) {
                                        authorization = cmsSession.getAuthorization();
@@ -159,7 +156,7 @@ public class HttpSessionLoginModule implements LoginModule {
                return true;
        }
 
-       private void extractHttpAuth(final HttpServletRequest httpRequest) {
+       private void extractHttpAuth(final HttpRequest httpRequest) {
                String authHeader = httpRequest.getHeader(CmsAuthUtils.HEADER_AUTHORIZATION);
                extractHttpAuth(authHeader);
        }
@@ -206,7 +203,7 @@ public class HttpSessionLoginModule implements LoginModule {
                // }
        }
 
-       private void extractClientCertificate(HttpServletRequest req) {
+       private void extractClientCertificate(HttpRequest req) {
                X509Certificate[] certs = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
                if (null != certs && certs.length > 0) {// Servlet container verified the client certificate
                        String certDn = certs[0].getSubjectX500Principal().getName();
index ec6b5a30c196b77b7bde1ed4c10cb0f7e8568d31..f5e4085c32a97e456822e60877c99f8ef121b473 100644 (file)
@@ -9,7 +9,6 @@ import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
-import javax.servlet.http.HttpServletRequest;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -43,7 +42,7 @@ public class IdentLoginModule implements LoginModule {
                } catch (UnsupportedCallbackException e) {
                        return false;
                }
-               HttpServletRequest request = httpCallback.getRequest();
+               HttpRequest request = httpCallback.getRequest();
                if (request == null)
                        return false;
                IdentClient identClient = Activator.getIdentClient(request.getRemoteAddr());
index 240564f9ec894b809c956829e01fc653dc8d0942..5d46839e0be753e9ea18cb01bdded345ce788c06 100644 (file)
@@ -12,7 +12,6 @@ import javax.security.auth.kerberos.KerberosPrincipal;
 import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
 import javax.security.auth.x500.X500Principal;
-import javax.servlet.http.HttpServletRequest;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -68,7 +67,7 @@ public class SingleUserLoginModule implements LoginModule {
                        authorizationName = principal.getName();
                }
 
-               HttpServletRequest request = (HttpServletRequest) sharedState.get(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST);
+               HttpRequest request = (HttpRequest) sharedState.get(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST);
                Locale locale = Locale.getDefault();
                if (request != null)
                        locale = request.getLocale();
index 27de54be35567496e81c14477b3ae3f9b4768eb5..568e2f6e0f6d085794e84932e7ff5b241d3cef60 100644 (file)
@@ -132,4 +132,8 @@ public class SpnegoLoginModule implements LoginModule {
                return null;
 
        }
+
+       public static boolean hasAcceptorCredentials() {
+               return Activator.getAcceptorCredentials() != null;
+       }
 }
index 092a06b7778e8bd6ecbcff7b53293ce3494a36b2..d526f4fc2feb338fb0b093d1b7f8f5a979f1fdad 100644 (file)
@@ -23,7 +23,6 @@ import javax.security.auth.kerberos.KerberosPrincipal;
 import javax.security.auth.login.CredentialNotFoundException;
 import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
-import javax.servlet.http.HttpServletRequest;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -253,7 +252,7 @@ public class UserAdminLoginModule implements LoginModule {
                }
 
                // Log and monitor new login
-               HttpServletRequest request = (HttpServletRequest) sharedState.get(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST);
+               HttpRequest request = (HttpRequest) sharedState.get(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST);
                CmsAuthUtils.addAuthorization(subject, authorization);
 
                // Unlock keyring (underlying login to the JCR repository)
index 5753decf9ed2c565d5f011795371e99620b9154d..5485fc5ee112ad445995a18c61c6523e2ff7855e 100644 (file)
@@ -62,7 +62,7 @@ public class CmsUserManagerImpl implements CmsUserManager {
 //     private Map<String, String> serviceProperties;
        private WorkTransaction userTransaction;
 
-       private Map<UserDirectory, Hashtable<String, String>> userDirectories = Collections
+       private Map<UserDirectory, Hashtable<String, Object>> userDirectories = Collections
                        .synchronizedMap(new LinkedHashMap<>());
 
        @Override
@@ -481,11 +481,11 @@ public class CmsUserManagerImpl implements CmsUserManager {
                this.userTransaction = userTransaction;
        }
 
-       public void addUserDirectory(UserDirectory userDirectory, Map<String, String> properties) {
+       public void addUserDirectory(UserDirectory userDirectory, Map<String, Object> properties) {
                userDirectories.put(userDirectory, new Hashtable<>(properties));
        }
 
-       public void removeUserDirectory(UserDirectory userDirectory, Map<String, String> properties) {
+       public void removeUserDirectory(UserDirectory userDirectory, Map<String, Object> properties) {
                userDirectories.remove(userDirectory);
        }
 
diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/HttpUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/http/HttpUtils.java
deleted file mode 100644 (file)
index b5d3553..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.argeo.cms.internal.http;
-
-import java.util.Enumeration;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.logging.Log;
-
-public class HttpUtils {
-       public final static String HEADER_AUTHORIZATION = "Authorization";
-       public final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
-
-       static boolean isBrowser(String userAgent) {
-               return userAgent.contains("webkit") || userAgent.contains("gecko") || userAgent.contains("firefox")
-                               || userAgent.contains("msie") || userAgent.contains("chrome") || userAgent.contains("chromium")
-                               || userAgent.contains("opera") || userAgent.contains("browser");
-       }
-
-       public static void logResponseHeaders(Log log, HttpServletResponse response) {
-               if (!log.isDebugEnabled())
-                       return;
-               for (String headerName : response.getHeaderNames()) {
-                       Object headerValue = response.getHeader(headerName);
-                       log.debug(headerName + ": " + headerValue);
-               }
-       }
-
-       public static void logRequestHeaders(Log log, HttpServletRequest request) {
-               if (!log.isDebugEnabled())
-                       return;
-               for (Enumeration<String> headerNames = request.getHeaderNames(); headerNames.hasMoreElements();) {
-                       String headerName = headerNames.nextElement();
-                       Object headerValue = request.getHeader(headerName);
-                       log.debug(headerName + ": " + headerValue);
-               }
-               log.debug(request.getRequestURI() + "\n");
-       }
-
-       public static void logRequest(Log log, HttpServletRequest request) {
-               log.debug("contextPath=" + request.getContextPath());
-               log.debug("servletPath=" + request.getServletPath());
-               log.debug("requestURI=" + request.getRequestURI());
-               log.debug("queryString=" + request.getQueryString());
-               StringBuilder buf = new StringBuilder();
-               // headers
-               Enumeration<String> en = request.getHeaderNames();
-               while (en.hasMoreElements()) {
-                       String header = en.nextElement();
-                       Enumeration<String> values = request.getHeaders(header);
-                       while (values.hasMoreElements())
-                               buf.append("  " + header + ": " + values.nextElement());
-                       buf.append('\n');
-               }
-
-               // attributed
-               Enumeration<String> an = request.getAttributeNames();
-               while (an.hasMoreElements()) {
-                       String attr = an.nextElement();
-                       Object value = request.getAttribute(attr);
-                       buf.append("  " + attr + ": " + value);
-                       buf.append('\n');
-               }
-               log.debug("\n" + buf);
-       }
-
-       private HttpUtils() {
-
-       }
-}
diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/PkgServlet.java b/org.argeo.cms/src/org/argeo/cms/internal/http/PkgServlet.java
deleted file mode 100644 (file)
index 26046b2..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-package org.argeo.cms.internal.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Collection;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.io.IOUtils;
-import org.argeo.cms.osgi.PublishNamespace;
-import org.argeo.osgi.util.FilterRequirement;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.Version;
-import org.osgi.framework.VersionRange;
-import org.osgi.framework.namespace.PackageNamespace;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleWiring;
-import org.osgi.framework.wiring.FrameworkWiring;
-import org.osgi.resource.Requirement;
-
-public class PkgServlet extends HttpServlet {
-       private static final long serialVersionUID = 7660824185145214324L;
-
-       private BundleContext bundleContext = FrameworkUtil.getBundle(PkgServlet.class).getBundleContext();
-
-       @Override
-       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-               String pathInfo = req.getPathInfo();
-
-               String pkg, versionStr, file;
-               String[] parts = pathInfo.split("/");
-               // first is always empty
-               if (parts.length == 4) {
-                       pkg = parts[1];
-                       versionStr = parts[2];
-                       file = parts[3];
-               } else if (parts.length == 3) {
-                       pkg = parts[1];
-                       versionStr = null;
-                       file = parts[2];
-               } else {
-                       throw new IllegalArgumentException("Unsupported path length " + pathInfo);
-               }
-
-               FrameworkWiring frameworkWiring = bundleContext.getBundle(0).adapt(FrameworkWiring.class);
-               String filter;
-               if (versionStr == null) {
-                       filter = "(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")";
-               } else {
-                       if (versionStr.startsWith("[") || versionStr.startsWith("(")) {// range
-                               VersionRange versionRange = new VersionRange(versionStr);
-                               filter = "(&(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")"
-                                               + versionRange.toFilterString(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE) + ")";
-
-                       } else {
-                               Version version = new Version(versionStr);
-                               filter = "(&(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")("
-                                               + PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE + "=" + version + "))";
-                       }
-               }
-               Requirement requirement = new FilterRequirement(PackageNamespace.PACKAGE_NAMESPACE, filter);
-               Collection<BundleCapability> packages = frameworkWiring.findProviders(requirement);
-               if (packages.isEmpty()) {
-                       resp.sendError(404);
-                       return;
-               }
-
-               // TODO verify that it works with multiple versions
-               SortedMap<Version, BundleCapability> sorted = new TreeMap<>();
-               for (BundleCapability capability : packages) {
-                       sorted.put(capability.getRevision().getVersion(), capability);
-               }
-
-               Bundle bundle = sorted.get(sorted.firstKey()).getRevision().getBundle();
-               String entryPath = '/' + pkg.replace('.', '/') + '/' + file;
-               URL internalURL = bundle.getResource(entryPath);
-               if (internalURL == null) {
-                       resp.sendError(404);
-                       return;
-               }
-
-               // Resource found, we now check whether it can be published
-               boolean publish = false;
-               BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
-               capabilities: for (BundleCapability bundleCapability : bundleWiring
-                               .getCapabilities(PublishNamespace.CMS_PUBLISH_NAMESPACE)) {
-                       Object publishedPkg = bundleCapability.getAttributes().get(PublishNamespace.PKG);
-                       if (publishedPkg != null) {
-                               if (publishedPkg.equals("*") || publishedPkg.equals(pkg)) {
-                                       Object publishedFile = bundleCapability.getAttributes().get(PublishNamespace.FILE);
-                                       if (publishedFile == null) {
-                                               publish = true;
-                                               break capabilities;
-                                       } else {
-                                               String[] publishedFiles = publishedFile.toString().split(",");
-                                               for (String pattern : publishedFiles) {
-                                                       if (pattern.startsWith("*.")) {
-                                                               String ext = pattern.substring(1);
-                                                               if (file.endsWith(ext)) {
-                                                                       publish = true;
-                                                                       break capabilities;
-                                                               }
-                                                       } else {
-                                                               if (publishedFile.equals(file)) {
-                                                                       publish = true;
-                                                                       break capabilities;
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               if (!publish) {
-                       resp.sendError(404);
-                       return;
-               }
-
-               try (InputStream in = internalURL.openStream()) {
-                       IOUtils.copy(in, resp.getOutputStream());
-               }
-       }
-
-}
diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/RobotServlet.java b/org.argeo.cms/src/org/argeo/cms/internal/http/RobotServlet.java
deleted file mode 100644 (file)
index 6d3d302..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.argeo.cms.internal.http;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-public class RobotServlet extends HttpServlet {
-       private static final long serialVersionUID = 7935661175336419089L;
-
-       @Override
-       protected void service(HttpServletRequest request, HttpServletResponse response)
-                       throws ServletException, IOException {
-               PrintWriter writer = response.getWriter();
-               writer.append("User-agent: *\n");
-               writer.append("Disallow:\n");
-               response.setHeader("Content-Type", "text/plain");
-               writer.flush();
-       }
-
-}
index ce819051870b11dd59caf3c37bab451db4855625..03fb82faac46d1c204855e01ea43730ad8bb05af 100644 (file)
@@ -3,9 +3,9 @@ package org.argeo.cms.internal.http;
 import java.util.Locale;
 
 import javax.security.auth.Subject;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
 
+import org.argeo.cms.auth.HttpRequest;
+import org.argeo.cms.auth.HttpSession;
 import org.argeo.cms.internal.auth.CmsSessionImpl;
 import org.osgi.service.useradmin.Authorization;
 
@@ -15,24 +15,19 @@ public class WebCmsSessionImpl extends CmsSessionImpl {
        private HttpSession httpSession;
 
        public WebCmsSessionImpl(Subject initialSubject, Authorization authorization, Locale locale,
-                       HttpServletRequest request) {
-               super(initialSubject, authorization, locale, request.getSession(false).getId());
-               httpSession = request.getSession(false);
+                       HttpRequest request) {
+               super(initialSubject, authorization, locale, request.getSession().getId());
+               httpSession = request.getSession();
        }
 
        @Override
        public boolean isValid() {
                if (isClosed())
                        return false;
-               try {// test http session
-                       httpSession.getCreationTime();
-                       return true;
-               } catch (IllegalStateException ise) {
-                       return false;
-               }
+               return httpSession.isValid();
        }
 
-       public static CmsSessionImpl getCmsSession(HttpServletRequest request) {
-               return CmsSessionImpl.getByLocalId(request.getSession(false).getId());
+       public static CmsSessionImpl getCmsSession(HttpRequest request) {
+               return CmsSessionImpl.getByLocalId(request.getSession().getId());
        }
 }
index 86c6c9c31a66721cdb9acd9c2a0c373a1af2f6ce..11efa9e0f9dc9920520b9f800a9b7c17d9061bce 100644 (file)
@@ -34,10 +34,13 @@ import org.apache.commons.httpclient.params.HttpParams;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.api.NodeConstants;
+import org.argeo.cms.CmsUserManager;
+import org.argeo.cms.internal.auth.CmsUserManagerImpl;
 import org.argeo.cms.internal.http.client.HttpCredentialProvider;
 import org.argeo.cms.internal.http.client.SpnegoAuthScheme;
 import org.argeo.naming.DnsBrowser;
 import org.argeo.osgi.transaction.WorkControl;
+import org.argeo.osgi.transaction.WorkTransaction;
 import org.argeo.osgi.useradmin.AbstractUserDirectory;
 import org.argeo.osgi.useradmin.AggregatingUserAdmin;
 import org.argeo.osgi.useradmin.LdapUserAdmin;
@@ -52,6 +55,7 @@ import org.ietf.jgss.GSSName;
 import org.ietf.jgss.Oid;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.cm.ManagedServiceFactory;
 import org.osgi.service.useradmin.Authorization;
@@ -82,11 +86,25 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor
        private boolean singleUser = false;
 //     private boolean systemRolesAvailable = false;
 
+       CmsUserManagerImpl userManager;
+
        public NodeUserAdmin(String systemRolesBaseDn, String tokensBaseDn) {
                super(systemRolesBaseDn, tokensBaseDn);
                BundleContext bc = Activator.getBundleContext();
                if (bc != null) {
-                       tmTracker = new ServiceTracker<>(bc, WorkControl.class, null);
+                       tmTracker = new ServiceTracker<>(bc, WorkControl.class, null) {
+
+                               @Override
+                               public WorkControl addingService(ServiceReference<WorkControl> reference) {
+                                       WorkControl workControl = super.addingService(reference);
+                                       userManager = new CmsUserManagerImpl();
+                                       userManager.setUserAdmin(NodeUserAdmin.this);
+                                       // FIXME make it more robust
+                                       userManager.setUserTransaction((WorkTransaction) workControl);
+                                       bc.registerService(CmsUserManager.class, userManager, null);
+                                       return workControl;
+                               }
+                       };
                        tmTracker.open();
                } else {
                        tmTracker = null;
@@ -128,7 +146,7 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor
 
                // OSGi
                LdapName baseDn = userDirectory.getBaseDn();
-               Dictionary<String, Object> regProps = new Hashtable<>();
+               Hashtable<String, Object> regProps = new Hashtable<>();
                regProps.put(Constants.SERVICE_PID, pid);
                if (isSystemRolesBaseDn(baseDn))
                        regProps.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE);
@@ -136,6 +154,7 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor
                // ServiceRegistration<UserDirectory> reg =
                // bc.registerService(UserDirectory.class, userDirectory, regProps);
                Activator.registerService(UserDirectory.class, userDirectory, regProps);
+               userManager.addUserDirectory(userDirectory, regProps);
                pidToBaseDn.put(pid, baseDn);
                // pidToServiceRegs.put(pid, reg);
 
diff --git a/org.argeo.cms/src/org/argeo/cms/servlet/CmsServletContext.java b/org.argeo.cms/src/org/argeo/cms/servlet/CmsServletContext.java
deleted file mode 100644 (file)
index c88ee7f..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.argeo.cms.servlet;
-
-import java.io.IOException;
-import java.net.URL;
-import java.security.PrivilegedAction;
-import java.util.Map;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.api.NodeConstants;
-import org.argeo.cms.auth.HttpRequestCallbackHandler;
-import org.argeo.cms.internal.http.HttpUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.service.http.context.ServletContextHelper;
-
-/**
- * Default servlet context degrading to anonymous if the the session is not
- * pre-authenticated.
- */
-public class CmsServletContext extends ServletContextHelper {
-       private final static Log log = LogFactory.getLog(CmsServletContext.class);
-       // use CMS bundle for resources
-       private Bundle bundle = FrameworkUtil.getBundle(getClass());
-
-       public void init(Map<String, String> properties) {
-
-       }
-
-       public void destroy() {
-
-       }
-
-       @Override
-       public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException {
-               if (log.isTraceEnabled())
-                       HttpUtils.logRequestHeaders(log, request);
-               LoginContext lc;
-               try {
-                       lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request, response));
-                       lc.login();
-               } catch (LoginException e) {
-                       lc = processUnauthorized(request, response);
-                       if (log.isTraceEnabled())
-                               HttpUtils.logResponseHeaders(log, response);
-                       if (lc == null)
-                               return false;
-               }
-               
-               Subject subject = lc.getSubject();
-               //log.debug("SERVLET CONTEXT: "+subject);
-               Subject.doAs(subject, new PrivilegedAction<Void>() {
-
-                       @Override
-                       public Void run() {
-                               // TODO also set login context in order to log out ?
-                               ServletAuthUtils.configureRequestSecurity(request);
-                               return null;
-                       }
-
-               });
-               return true;
-       }
-
-       @Override
-       public void finishSecurity(HttpServletRequest request, HttpServletResponse response) {
-               ServletAuthUtils.clearRequestSecurity(request);
-       }
-
-       protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) {
-               // anonymous
-               try {
-                       LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS,
-                                       new HttpRequestCallbackHandler(request, response));
-                       lc.login();
-                       return lc;
-               } catch (LoginException e1) {
-                       if (log.isDebugEnabled())
-                               log.error("Cannot log in as anonymous", e1);
-                       return null;
-               }
-       }
-
-       @Override
-       public URL getResource(String name) {
-               return bundle.getResource(name);
-       }
-
-}
diff --git a/org.argeo.cms/src/org/argeo/cms/servlet/PrivateWwwAuthServletContext.java b/org.argeo.cms/src/org/argeo/cms/servlet/PrivateWwwAuthServletContext.java
deleted file mode 100644 (file)
index e454750..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.argeo.cms.servlet;
-
-import javax.security.auth.login.LoginContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.argeo.cms.internal.http.HttpUtils;
-
-/** Servlet context forcing authentication. */
-public class PrivateWwwAuthServletContext extends CmsServletContext {
-       // TODO make it configurable
-       private final String httpAuthRealm = "Argeo";
-       private final boolean forceBasic = false;
-
-       @Override
-       protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) {
-               askForWwwAuth(request, response);
-               return null;
-       }
-
-       protected void askForWwwAuth(HttpServletRequest request, HttpServletResponse response) {
-               // response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic
-               // realm=\"" + httpAuthRealm + "\"");
-               if (org.argeo.cms.internal.kernel.Activator.getAcceptorCredentials() != null && !forceBasic)// SPNEGO
-                       response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "Negotiate");
-               else
-                       response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "Basic realm=\"" + httpAuthRealm + "\"");
-
-               // response.setDateHeader("Date", System.currentTimeMillis());
-               // response.setDateHeader("Expires", System.currentTimeMillis() + (24 *
-               // 60 * 60 * 1000));
-               // response.setHeader("Accept-Ranges", "bytes");
-               // response.setHeader("Connection", "Keep-Alive");
-               // response.setHeader("Keep-Alive", "timeout=5, max=97");
-               // response.setContentType("text/html; charset=UTF-8");         
-               response.setStatus(401);
-       }
-}
diff --git a/org.argeo.cms/src/org/argeo/cms/servlet/ServletAuthUtils.java b/org.argeo.cms/src/org/argeo/cms/servlet/ServletAuthUtils.java
deleted file mode 100644 (file)
index 67db467..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.argeo.cms.servlet;
-
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.function.Supplier;
-
-import javax.security.auth.Subject;
-import javax.servlet.http.HttpServletRequest;
-
-import org.argeo.api.cms.CmsSession;
-import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.osgi.CmsOsgiUtils;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.service.http.HttpContext;
-
-/** Authentications utilities when using servlets. */
-public class ServletAuthUtils {
-       private static BundleContext bundleContext = FrameworkUtil.getBundle(ServletAuthUtils.class).getBundleContext();
-
-       /**
-        * Execute this supplier, using the CMS class loader as context classloader.
-        * Useful to log in to JCR.
-        */
-       public final static <T> T doAs(Supplier<T> supplier, HttpServletRequest req) {
-               ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
-               Thread.currentThread().setContextClassLoader(ServletAuthUtils.class.getClassLoader());
-               try {
-                       return Subject.doAs(
-                                       Subject.getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName())),
-                                       new PrivilegedAction<T>() {
-
-                                               @Override
-                                               public T run() {
-                                                       return supplier.get();
-                                               }
-
-                                       });
-               } finally {
-                       Thread.currentThread().setContextClassLoader(currentContextCl);
-               }
-       }
-
-       public final static void configureRequestSecurity(HttpServletRequest req) {
-               if (req.getAttribute(AccessControlContext.class.getName()) != null)
-                       throw new IllegalStateException("Request already authenticated.");
-               AccessControlContext acc = AccessController.getContext();
-               req.setAttribute(HttpContext.REMOTE_USER, CurrentUser.getUsername());
-               req.setAttribute(AccessControlContext.class.getName(), acc);
-       }
-
-       public final static void clearRequestSecurity(HttpServletRequest req) {
-               if (req.getAttribute(AccessControlContext.class.getName()) == null)
-                       throw new IllegalStateException("Cannot clear non-authenticated request.");
-               req.setAttribute(HttpContext.REMOTE_USER, null);
-               req.setAttribute(AccessControlContext.class.getName(), null);
-       }
-
-       public static CmsSession getCmsSession(HttpServletRequest req) {
-               Subject subject = Subject
-                               .getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName()));
-               CmsSession cmsSession = CmsOsgiUtils.getCmsSession(bundleContext, subject);
-               return cmsSession;
-       }
-}
diff --git a/pom.xml b/pom.xml
index bb88071775b54e2b02d3217663974a03d0eead1a..123fb1c9ca8051fb7502d1117a96e6ed9cac4931 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -31,6 +31,7 @@
                <module>org.argeo.transition</module>
                <!-- <module>org.argeo.maintenance</module> -->
                <module>org.argeo.cms</module>
+               <module>org.argeo.cms.servlet</module>
                <module>org.argeo.cms.swt</module>
                <module>org.argeo.cms.jcr</module>
                <!-- <module>org.argeo.cms.ui.theme</module> -->