5

我已经创建了网络服务。它工作正常。现在我正在尝试对其进行身份验证。为此,我正在使用 CXF 拦截器。由于某种原因,拦截器不会开火。我错过了什么?这是我的第一个网络服务。

import javax.annotation.Resource;
import javax.inject.Inject;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;

import org.apache.cxf.interceptor.InInterceptors;

@WebService
@InInterceptors(interceptors = "ws.BasicAuthAuthorizationInterceptor")
public class Service {

    @WebMethod
    public void test(@WebParam(name = "value") Integer value) throws Exception {
        System.out.println("Value = " + value);
    }    
}

-

package ws;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.cxf.binding.soap.interceptor.SoapHeaderInterceptor;
import org.apache.cxf.configuration.security.AuthorizationPolicy;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.transport.Conduit;
import org.apache.cxf.ws.addressing.EndpointReferenceType;

public class BasicAuthAuthorizationInterceptor extends SoapHeaderInterceptor {

@Override
public void handleMessage(Message message) throws Fault {
    System.out.println("**** GET THIS LINE TO CONSOLE TO SEE IF INTERCEPTOR IS FIRING!!!");
    AuthorizationPolicy policy = message.get(AuthorizationPolicy.class);

    // If the policy is not set, the user did not specify credentials.
    // 401 is sent to the client to indicate that authentication is required.
    if (policy == null) {
        sendErrorResponse(message, HttpURLConnection.HTTP_UNAUTHORIZED);
        return;
    }

    String username = policy.getUserName();
    String password = policy.getPassword();

    // CHECK USERNAME AND PASSWORD
    if (!checkLogin(username, password)) {
        System.out.println("handleMessage: Invalid username or password for user: "
                + policy.getUserName());
        sendErrorResponse(message, HttpURLConnection.HTTP_FORBIDDEN);
    }
}

private boolean checkLogin(String username, String password) {
    if (username.equals("admin") && password.equals("admin")) {
        return true;
    }
    return false;
}

private void sendErrorResponse(Message message, int responseCode) {
    Message outMessage = getOutMessage(message);
    outMessage.put(Message.RESPONSE_CODE, responseCode);

    // Set the response headers
    @SuppressWarnings("unchecked")
    Map<String, List<String>> responseHeaders = (Map<String, List<String>>) message
            .get(Message.PROTOCOL_HEADERS);

    if (responseHeaders != null) {
        responseHeaders.put("WWW-Authenticate", Arrays.asList(new String[] { "Basic realm=realm" }));
        responseHeaders.put("Content-Length", Arrays.asList(new String[] { "0" }));
    }
    message.getInterceptorChain().abort();
    try {
        getConduit(message).prepare(outMessage);
        close(outMessage);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private Message getOutMessage(Message inMessage) {
    Exchange exchange = inMessage.getExchange();
    Message outMessage = exchange.getOutMessage();
    if (outMessage == null) {
        Endpoint endpoint = exchange.get(Endpoint.class);
        outMessage = endpoint.getBinding().createMessage();
        exchange.setOutMessage(outMessage);
    }
    outMessage.putAll(inMessage);
    return outMessage;
}

private Conduit getConduit(Message inMessage) throws IOException {
    Exchange exchange = inMessage.getExchange();
    EndpointReferenceType target = exchange.get(EndpointReferenceType.class);
    Conduit conduit = exchange.getDestination().getBackChannel(inMessage, null, target);
    exchange.setConduit(conduit);
    return conduit;
}

private void close(Message outMessage) throws IOException {
    OutputStream os = outMessage.getContent(OutputStream.class);
    os.flush();
    os.close();
}

}

我现在正在为此奋斗几天。不知道再谷歌什么了。帮助表示赞赏。

4

2 回答 2

8

我找到了解决方案。我在战争项目的 MANIFEST.MF 文件中缺少以下行:

依赖:org.apache.cxf

Maven 自己并没有包含这条线,所以我必须找到解决方法。我在这里找到了。它说:在端点/处理程序上使用注释时,例如 Apache CXF (@InInterceptor、@GZIP、...),请记住在清单中添加正确的模块依赖项。否则,您的注释不会被 JBoss Application Server 7 拾取并添加到注释索引中,从而导致它们被完全忽略。

是我发现如何更改 MANIFEST.MF 文件的地方。

简而言之,我在我的项目中添加了自定义清单文件,并在 pom.xml 中引用了它。希望这可以帮助某人。

于 2013-06-17T14:14:31.843 回答
2

Felix提供的答案是准确的。我设法按照他的指示解决了这个问题。只是为了完成这里是 maven 配置,它允许您使用放置在 META-INF 文件夹中的自己的 MANIFEST.MF 文件。

       <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <archive>
                    <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
                </archive>
            </configuration>
        </plugin>

这里是我使用的 MANIFEST.MF 文件内容的相关内容。

Manifest-Version: 1.0
Description: yourdescription
Dependencies: org.apache.ws.security,org.apache.cxf
于 2014-09-17T09:29:52.137 回答