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, [email protected] 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>