Repository: cxf Updated Branches: refs/heads/master 774347c5d -> 8ebe5261f
[CXF-5922]Secure CXF WSDL with standard HTTP Authentication Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/8ebe5261 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/8ebe5261 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/8ebe5261 Branch: refs/heads/master Commit: 8ebe5261f0dcb792de4acb4057b611dd446b4bd4 Parents: 774347c Author: Freeman Fang <[email protected]> Authored: Thu Aug 21 13:07:05 2014 +0800 Committer: Freeman Fang <[email protected]> Committed: Thu Aug 21 13:07:05 2014 +0800 ---------------------------------------------------------------------- .../auth/WSDLGetAuthenticatorInterceptor.java | 142 +++++++++++++++++++ 1 file changed, 142 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/8ebe5261/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/WSDLGetAuthenticatorInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/WSDLGetAuthenticatorInterceptor.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/WSDLGetAuthenticatorInterceptor.java new file mode 100644 index 0000000..ffff019 --- /dev/null +++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/WSDLGetAuthenticatorInterceptor.java @@ -0,0 +1,142 @@ +/** + * 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.http.auth; + +import java.io.IOException; +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.HttpServletResponse; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.common.util.StringUtils; +import org.apache.cxf.configuration.security.AuthorizationPolicy; +import org.apache.cxf.endpoint.Endpoint; +import org.apache.cxf.interceptor.Fault; +import org.apache.cxf.message.Message; +import org.apache.cxf.phase.AbstractPhaseInterceptor; +import org.apache.cxf.phase.Phase; + +public class WSDLGetAuthenticatorInterceptor extends AbstractPhaseInterceptor<Message> { + + private static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate"; + + private static final String AUTHENTICATION_SCHEME_BASIC = "Basic"; + + private static final Logger LOG = LogUtils.getL7dLogger(WSDLGetAuthenticatorInterceptor.class); + + private String contextName; + + public WSDLGetAuthenticatorInterceptor() { + super(Phase.READ); + getBefore().add("org.apache.cxf.frontend.WSDLGetInterceptor"); + } + + public void handleMessage(Message message) throws Fault { + + String method = (String)message.get(Message.HTTP_REQUEST_METHOD); + String query = (String)message.get(Message.QUERY_STRING); + if (!"GET".equals(method) || StringUtils.isEmpty(query)) { + return; + } + Endpoint endpoint = message.getExchange().getEndpoint(); + synchronized (endpoint) { + if (!StringUtils.isEmpty(contextName)) { + AuthorizationPolicy policy = message.get(AuthorizationPolicy.class); + if (policy == null) { + //should return 401 + LOG.info("=====> no authorization header, should return 401"); + handle401response(message, endpoint); + return; + } else { + Subject subject = (Subject)authenticate(policy.getUserName(), policy.getPassword()); + if (subject == null) { + LOG.info("=====> login failed, should return 401"); + handle401response(message, endpoint); + return; + } + } + + } + + } + } + + private void handle401response(Message message, Endpoint e) { + HttpServletResponse response = (HttpServletResponse)message.get("HTTP.RESPONSE"); + response.setHeader(HEADER_WWW_AUTHENTICATE, AUTHENTICATION_SCHEME_BASIC + " realm=\"" + contextName + "\""); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.setContentLength(0); + LOG.info("=====> reset response header"); + message.getInterceptorChain().pause(); + } + + 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(getContextName(), 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 String getContextName() { + return contextName; + } + + public void setContextName(String contextName) { + this.contextName = contextName; + } + +}
