CXF学习笔记(4)-HelloWorld!-安全认证

鉴客 发布于 2011/08/18 17:03
阅读 4K+
收藏 8

前3节中介绍了如何发布一个webservice和客户端如何调用,一切貌似都正常,但存在着安全隐患-这样导致任意的客户端都可以调用我们的webservice服务,接下来将介绍如何采用基于用户名和密码认证的方式来实现客户端调用

1.服务器端配置

a.在发布service的时候为该service添加一个WSS4JInInterceptor 拦截器

表示我们的service需要用户提供用户名和密码认证后才能调用

package com.crazycoder2010.webservice.cxf.server;  
  
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;

import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.frontend.ServerFactoryBean;
import org.apache.cxf.service.invoker.BeanInvoker;
import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.handler.WSHandlerConstants;  
  
<span><span class="keyword"></span></span>import com.crazycoder2010.webservice.cxf.server.HelloWorldServiceImpl;  
  
public class WebServiceServlet extends CXFNonSpringServlet {  
    private static final long serialVersionUID = -5314312869027558456L;  
  
    @Override  
    protected void loadBus(ServletConfig servletConfig) {  
        super.loadBus(servletConfig);  
        System.out.println("#####################");  
        ServerFactoryBean svrFactory = new ServerFactoryBean();
        svrFactory.setServiceClass(HelloWorldService.class);
        svrFactory.setAddress("/passportService");
        svrFactory.setInvoker(new BeanInvoker(new HelloWorldServiceImp()));
        Server server = svrFactory.create();
        Endpoint cxfEndpoint = server.getEndpoint();
        Map<String, Object> inProps = new HashMap<String, Object>();
        inProps.put(WSHandlerConstants.ACTION,
                WSHandlerConstants.USERNAME_TOKEN);
        inProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
        inProps.put(WSHandlerConstants.PW_CALLBACK_CLASS,
                ServerPasswordHandler.class.getName());
        cxfEndpoint.getInInterceptors().add(new WSS4JInInterceptor(inProps));
    }  
}

b.处理用户名和密码的逻辑

添加一个ServerPasswordHandler类,该类实现CallbackHandler接口,user='kevin',password='111111'为该service的访问用户名密码

public class ServerPasswordHandler implements CallbackHandler{
	private String user = "kevin";
	private String password = "111111";
	@Override
	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
		if(user.equals(pc.getIdentifier())){
			pc.setPassword(password);
		}
	}
}

2.客户端配置

a.配置WSS4JOutInterceptor拦截器,表示发出请求的时候将以提供的用户名和密码信息提交到服务器端认证

public class WebServiceFactory {
	public static PassportService getHelloWorldService(){
	Map<String,Object> outProps = new HashMap<String,Object>();
	outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
	outProps.put(WSHandlerConstants.USER, "kevin");//这个用户即服务器端配置的用户名
	outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
	outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordHandler.class.getName());//这个类用来获取客户端认证用户名密码信息
	JaxWsProxyFactoryBean bean = new JaxWsProxyFactoryBean();  
        bean.getInInterceptors().add(new LoggingInInterceptor());  
        bean.getInFaultInterceptors().add(new LoggingOutInterceptor()); 
        bean.setServiceClass(PassportService.class);
        bean.setAddress("http://localhost:8080/CXF-Server/webservice/helloWorldService"); 
        HelloWorldService helloWorldService = (HelloWorldService)bean.create();
        ClientProxy clientProxy = (ClientProxy)Proxy.getInvocationHandler(passportService);
        Client client = clientProxy.getClient();
        client.getOutInterceptors().add(new WSS4JOutInterceptor(outProps));//配置拦截器
        return helloWorldService;
	}
}

b.配置客户端认证信息类

public class ClientPasswordHandler implements CallbackHandler{
	@Override
	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
	WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
        pc.setPassword("kevin");//这个地方的用户名和密码与服务器端保持一致	
        pc.setIdentifier("111111");
	}
}

c.客户端调用

public class DemoClient {
	public static void main(String[] args) {
               HelloWorldService helloWorldService = WebServiceFactory.getHelloWorldService();
	       helloWorldService.sayHello("John");
	}
}

小结:

这种方式利用服务器端与客户端共享同一用户名密码的方式实现了webservice的安全访问,流程图如下

参考资料:http://cxf.apache.org/docs/ws-security.html

文章来自:http://blog.csdn.net/crazycoder2010/article/details/6695436

加载中
0
RainJ
RainJ
我觉得真正在企业开发的时候流程应该是逆向的!~+
0
星星爷
星星爷

@鉴客   我现在是客户端 想要访问 不知道怎么实现的 server, 只给出了wsdl和用户名 密码  这样做可以吗


就是楼上所说的 是反向的

0
bayer
bayer

客户端的代码中, PassportService(类?接口?)没有详细的实现,,,方法 public static PassportService getHelloWorldService(){}更是返回了一个HelloWorldService实例, 这让人摸不清头脑,,, 好歹瞎摸乱撞是走通了程序, 虽然还有很有疑问, 不解, 困惑, 但还是感谢楼主.

y
you__yuan
怎么走通的呢/ ? 没有PassportService
0
小文大哥哥
小文大哥哥
public class ServerPasswordHandler implements CallbackHandler{
    private String user = "kevin";
    private String password = "111111";
    @Override
    public void handle(Callback[] callbacks) throws IOException,
            UnsupportedCallbackException {
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
        if(user.equals(pc.getIdentifier())){
            pc.setPassword(password);
        }
    }
}

能否把这段代码解释下, user是写死的用户名,而实际情况下如何获取?
还有password如何获取?
返回顶部
顶部