You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ff...@apache.org on 2013/07/29 11:31:49 UTC
svn commit: r1507984 - in /cxf/trunk/rt/transports/http/src/main:
java/org/apache/cxf/transport/servlet/
java/org/apache/cxf/transport/servlet/servicelist/
resources/OSGI-INF/blueprint/
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>
Re: svn commit: r1507984 - in /cxf/trunk/rt/transports/http/src/main:
java/org/apache/cxf/transport/servlet/ java/org/apache/cxf/transport/servlet/servicelist/
resources/OSGI-INF/blueprint/
Posted by Sergey Beryozkin <sb...@gmail.com>.
Actually, does not make sense, obviously the request does not continue
after that, got confused
Sergey
On 29/07/13 10:41, Sergey Beryozkin wrote:
> 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, ffang@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>
>>
>>
>>
>
>
Re: svn commit: r1507984 - in /cxf/trunk/rt/transports/http/src/main: java/org/apache/cxf/transport/servlet/ java/org/apache/cxf/transport/servlet/servicelist/ resources/OSGI-INF/blueprint/
Posted by Freeman Fang <fr...@gmail.com>.
Hi Sergey,
Done, removed unnecessary attributes from HttpServletRequest if pass authentication.
Cheers
-------------
Freeman(Yue) Fang
Red Hat, Inc.
FuseSource is now part of Red Hat
Web: http://fusesource.com | http://www.redhat.com/
Twitter: freemanfang
Blog: http://freemanfang.blogspot.com
http://blog.sina.com.cn/u/1473905042
weibo: @Freeman小屋
On 2013-7-29, at 下午5:41, Sergey Beryozkin wrote:
> 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, ffang@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>
>>
>>
>>
>
>
Re: svn commit: r1507984 - in /cxf/trunk/rt/transports/http/src/main:
java/org/apache/cxf/transport/servlet/ java/org/apache/cxf/transport/servlet/servicelist/
resources/OSGI-INF/blueprint/
Posted by Sergey Beryozkin <sb...@gmail.com>.
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, ffang@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>
>
>
>