Hi Freeman

Can you please update ServiceListGeneratorServlet to actually remove the temp HTTPServletRequest attributes - because they are not needed any more after that ?

The reason is that these attributes will leak into JAX-RS ContainerRequestFilter.getProperties() - unfortunately this method has been tied to HTTPServletRequest attributes,

Thanks, Sergey

Thanks, Sergey
On 29/07/13 10:31, ff...@apache.org wrote:
Author: ffang
Date: Mon Jul 29 09:31:48 2013
New Revision: 1507984

URL: http://svn.apache.org/r1507984
Log:
[CXF-5165]add a JAAS authenticator for ServiceListPage

Added:
     
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListJAASAuthenticator.java
Modified:
     
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java
     
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java
     
cxf/trunk/rt/transports/http/src/main/resources/OSGI-INF/blueprint/osgiservlet.xml

Modified: 
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java?rev=1507984&r1=1507983&r2=1507984&view=diff
==============================================================================
--- 
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java
 (original)
+++ 
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/ServletController.java
 Mon Jul 29 09:31:48 2013
@@ -40,12 +40,17 @@ import org.apache.cxf.transport.http.Abs
  import org.apache.cxf.transport.http.DestinationRegistry;

  public class ServletController {
+
+    public static final String AUTH_SERVICE_LIST = "auth.service.list";
+    public static final String AUTH_SERVICE_LIST_REALM = 
"auth.service.list.realm";
      protected static final String DEFAULT_LISTINGS_CLASSIFIER = "/services";
      private static final Logger LOG = 
LogUtils.getL7dLogger(ServletController.class);
      private static final String HTTP_PREFIX = "http";
-
+
      protected boolean isHideServiceList;
+    protected boolean isAuthServiceListPage;
      protected boolean disableAddressUpdates;
+    protected String authServiceListPageRealm;
      protected String forcedBaseAddress;
      protected String serviceListRelativePath = DEFAULT_LISTINGS_CLASSIFIER;
      protected ServletConfig servletConfig;
@@ -108,6 +113,17 @@ public class ServletController {
          if (!StringUtils.isEmpty(hideServiceList)) {
              this.isHideServiceList = Boolean.valueOf(hideServiceList);
          }
+
+        String authServiceListPage = 
servletConfig.getInitParameter("service-list-page-authenticate");
+        if (!StringUtils.isEmpty(authServiceListPage)) {
+            this.isAuthServiceListPage = Boolean.valueOf(authServiceListPage);
+        }
+
+        String authServiceListRealm = 
servletConfig.getInitParameter("service-list-page-authenticate-realm");
+        if (!StringUtils.isEmpty(authServiceListRealm)) {
+            this.authServiceListPageRealm = authServiceListRealm;
+        }
+
          String isDisableAddressUpdates = 
servletConfig.getInitParameter("disable-address-updates");
          if (!StringUtils.isEmpty(isDisableAddressUpdates)) {
              this.disableAddressUpdates = 
Boolean.valueOf(isDisableAddressUpdates);
@@ -143,6 +159,9 @@ public class ServletController {
                      || request.getRequestURI().endsWith(serviceListRelativePath + 
"/")
                      || StringUtils.isEmpty(pathInfo)
                      || "/".equals(pathInfo))) {
+                    if (isAuthServiceListPage) {
+                        setAuthServiceListPageAttribute(request);
+                    }
                      setBaseURLAttribute(request);
                      serviceListGenerator.service(request, res);
                  } else {
@@ -188,6 +207,12 @@ public class ServletController {
          return true;
      }

+    private void setAuthServiceListPageAttribute(HttpServletRequest request) {
+        request.setAttribute(ServletController.AUTH_SERVICE_LIST, 
this.isAuthServiceListPage);
+        request.setAttribute(ServletController.AUTH_SERVICE_LIST_REALM, 
this.authServiceListPageRealm);
+
+    }
+
      public void invokeDestination(final HttpServletRequest request, 
HttpServletResponse response,
                                    AbstractHTTPDestination d) throws 
ServletException {
          if (LOG.isLoggable(Level.FINE)) {

Modified: 
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java?rev=1507984&r1=1507983&r2=1507984&view=diff
==============================================================================
--- 
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java
 (original)
+++ 
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java
 Mon Jul 29 09:31:48 2013
@@ -39,6 +39,7 @@ import org.apache.cxf.message.Message;
  import org.apache.cxf.service.model.EndpointInfo;
  import org.apache.cxf.transport.AbstractDestination;
  import org.apache.cxf.transport.http.DestinationRegistry;
+import org.apache.cxf.transport.servlet.ServletController;

  public class ServiceListGeneratorServlet extends HttpServlet {
      private static final long serialVersionUID = -113918058557537996L;
@@ -67,6 +68,19 @@ public class ServiceListGeneratorServlet
      @Override
      public void service(HttpServletRequest request,
                          HttpServletResponse response) throws 
ServletException, IOException {
+        Object obj = request.getAttribute(ServletController.AUTH_SERVICE_LIST);
+        boolean isAuthServiceList = false;
+        if (obj != null) {
+            isAuthServiceList = Boolean.valueOf(obj.toString());
+        }
+        if (isAuthServiceList) {
+            String authServiceListRealm = 
(String)request.getAttribute(ServletController.AUTH_SERVICE_LIST_REALM);
+            ServiceListJAASAuthenticator authenticator = new 
ServiceListJAASAuthenticator();
+            authenticator.setRealm(authServiceListRealm);
+            if (!authenticator.authenticate(request, response)) {
+                return;
+            }
+        }
          PrintWriter writer = response.getWriter();
          AbstractDestination[] destinations = 
destinationRegistry.getSortedDestinations();
          if (request.getParameter("stylesheet") != null) {

Added: 
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListJAASAuthenticator.java
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListJAASAuthenticator.java?rev=1507984&view=auto
==============================================================================
--- 
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListJAASAuthenticator.java
 (added)
+++ 
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListJAASAuthenticator.java
 Mon Jul 29 09:31:48 2013
@@ -0,0 +1,163 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.transport.servlet.servicelist;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.GeneralSecurityException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.AccountException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.Base64Exception;
+import org.apache.cxf.common.util.Base64Utility;
+import 
org.apache.cxf.transport.http.blueprint.HttpDestinationBPBeanDefinitionParser;
+
+
+
+public class ServiceListJAASAuthenticator {
+
+    private static final Logger LOG = 
LogUtils.getL7dLogger(HttpDestinationBPBeanDefinitionParser.class);
+
+    private static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
+
+    private static final String HEADER_AUTHORIZATION = "Authorization";
+
+    private static final String AUTHENTICATION_SCHEME_BASIC = "Basic";
+
+    private String realm;
+
+    public String getRealm() {
+        return realm;
+    }
+
+    public void setRealm(String realm) {
+        this.realm = realm;
+    }
+
+
+    public Object authenticate(final String username, final String password) {
+        return doAuthenticate(username, password);
+    }
+
+    public Subject doAuthenticate(final String username, final String 
password) {
+        try {
+            Subject subject = new Subject();
+            LoginContext loginContext = new LoginContext(realm, subject, new 
CallbackHandler() {
+                public void handle(Callback[] callbacks) throws IOException, 
UnsupportedCallbackException {
+                    for (int i = 0; i < callbacks.length; i++) {
+                        if (callbacks[i] instanceof NameCallback) {
+                            ((NameCallback)callbacks[i]).setName(username);
+                        } else if (callbacks[i] instanceof PasswordCallback) {
+                            
((PasswordCallback)callbacks[i]).setPassword(password.toCharArray());
+                        } else {
+                            throw new 
UnsupportedCallbackException(callbacks[i]);
+                        }
+                    }
+                }
+            });
+            loginContext.login();
+            return subject;
+        } catch (FailedLoginException e) {
+            LOG.log(Level.FINE, "Login failed ", e);
+            return null;
+        } catch (AccountException e) {
+            LOG.log(Level.WARNING, "Account failure ",  e);
+            return null;
+        } catch (GeneralSecurityException e) {
+            LOG.log(Level.SEVERE, "General Security Exception ", e);
+            return null;
+        }
+    }
+
+    public boolean authenticate(HttpServletRequest request, 
HttpServletResponse response) {
+        // Return immediately if the header is missing
+        String authHeader = request.getHeader(HEADER_AUTHORIZATION);
+        if (authHeader != null && authHeader.length() > 0) {
+
+            // Get the authType (Basic, Digest) and authInfo (user/password)
+            // from the header
+            authHeader = authHeader.trim();
+            int blank = authHeader.indexOf(' ');
+            if (blank > 0) {
+                String authType = authHeader.substring(0, blank);
+                String authInfo = authHeader.substring(blank).trim();
+
+
+                if (authType.equalsIgnoreCase(AUTHENTICATION_SCHEME_BASIC)) {
+                    try {
+                        String srcString = base64Decode(authInfo);
+
+                        int i = srcString.indexOf(':');
+                        String username = srcString.substring(0, i);
+                        String password = srcString.substring(i + 1);
+
+                        // authenticate
+                        Subject subject = doAuthenticate(username, password);
+                        if (subject != null) {
+                            return true;
+                        }
+
+                    } catch (Exception e) {
+                        // Ignore
+                    }
+                }
+            }
+        }
+
+        // request authentication
+        try {
+            response.setHeader(HEADER_WWW_AUTHENTICATE, AUTHENTICATION_SCHEME_BASIC + " 
realm=\""
+                                                        + this.realm + "\"");
+            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+            response.setContentLength(0);
+            response.flushBuffer();
+        } catch (IOException ioe) {
+            // failed sending the response ... cannot do anything about it
+        }
+
+        // inform HttpService that authentication failed
+        return false;
+    }
+
+    private static String base64Decode(String srcString) {
+        byte[] transformed = null;
+        try {
+            transformed = Base64Utility.decode(srcString);
+            return new String(transformed, "ISO-8859-1");
+        } catch (UnsupportedEncodingException uee) {
+            return srcString;
+        } catch (Base64Exception e) {
+            return srcString;
+        }
+    }
+
+}

Modified: 
cxf/trunk/rt/transports/http/src/main/resources/OSGI-INF/blueprint/osgiservlet.xml
URL: 
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/resources/OSGI-INF/blueprint/osgiservlet.xml?rev=1507984&r1=1507983&r2=1507984&view=diff
==============================================================================
--- 
cxf/trunk/rt/transports/http/src/main/resources/OSGI-INF/blueprint/osgiservlet.xml
 (original)
+++ 
cxf/trunk/rt/transports/http/src/main/resources/OSGI-INF/blueprint/osgiservlet.xml
 Mon Jul 29 09:31:48 2013
@@ -39,7 +39,8 @@ under the License.
        <cm:property name="org.apache.cxf.servlet.redirect-servlet-name" 
value=""/>
        <cm:property name="org.apache.cxf.servlet.redirect-servlet-path" 
value=""/>
        <cm:property name="org.apache.cxf.servlet.service-list-all-contexts" 
value=""/>
-
+      <cm:property name="org.apache.cxf.servlet.service-list-page-authenticate" 
value="false"/>
+      <cm:property name="org.apache.cxf.servlet.service-list-page-authenticate-realm" 
value="karaf"/>
      </cm:default-properties>

    </cm:property-placeholder>
@@ -64,6 +65,8 @@ under the License.
        <entry key="redirect-servlet-name" 
value="${org.apache.cxf.servlet.redirect-servlet-name}"/>
        <entry key="redirect-servlet-path" 
value="${org.apache.cxf.servlet.redirect-servlet-path}"/>
        <entry key="service-list-all-contexts" 
value="${org.apache.cxf.servlet.service-list-all-contexts}"/>
+      <entry key="service-list-page-authenticate" 
value="${org.apache.cxf.servlet.service-list-page-authenticate}"/>
+      <entry key="service-list-page-authenticate-realm" 
value="${org.apache.cxf.servlet.service-list-page-authenticate-realm}"/>
      </service-properties>
    </service>





Reply via email to