jax-ws之webservice security(安全)教程第二天

简介: 前言: 第一天里说了如何用jax-ws去结合ssh框架。 在今天的教程中将会向大家详细讲述一个ws-security中的一个传统的”基于handler”来认证客户端传来的用户名密码的webservice. 客户端传过来一对用户名和密码,服务端进行认证。

前言:

第一天里说了如何用jax-ws去结合ssh框架。

在今天的教程中将会向大家详细讲述一个ws-security中的一个传统的”基于handler”来认证客户端传来的用户名密码的webservice.

客户端传过来一对用户名和密码,服务端进行认证。

当然,我们此处说这个用户名和密码的传送,那可不是用下面的这种形式来传送的哦:  http://xxx.do?username=xxx&password=xxx

我们这个用户名和密码是带在soap报文中的, jax-ws用一个handler专门用于处理soap报文的。

一、书写Handler

1. 1 handler

package ctsjavacoe.ws.fromjava;

import java.util.*;

import javax.servlet.http.HttpServletRequest;

import javax.xml.namespace.QName;

import javax.xml.soap.*;

import javax.xml.ws.handler.MessageContext;

import javax.xml.ws.handler.soap.*;

import javax.xml.ws.soap.SOAPFaultException;

import org.apache.cxf.transport.http.*;

public class AuthValidationHandler implements SOAPHandler<SOAPMessageContext> {

         public Set<QName> getHeaders() {

                   // TODO Auto-generated method stub

                   return null;

         }

         public void close(MessageContext context) {

         }

         public boolean handleFault(SOAPMessageContext context) {

                   return false;

         }

         public boolean handleMessage(SOAPMessageContext context) {

 

                   HttpServletRequest request = (HttpServletRequest) context

                                     .get(AbstractHTTPDestination.HTTP_REQUEST);

                   //

                   if (request != null) {

                            System.out.println("Client IP:" + request.getRemoteAddr());

                   } else {

                            System.out.println("get client ip is null>>>>>>>>>");

                   }

 

                   Boolean outbound = (Boolean) context

                                     .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

 

                   if (!outbound.booleanValue()) {

                            SOAPMessage soapMessage = context.getMessage();

 

                            try {

                                     SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart()

                                                        .getEnvelope();

                                     SOAPHeader soapHeader = soapEnvelope.getHeader();

 

                                     if (soapHeader == null)

                                               generateSoapFault(soapMessage, "No Message Header...");

 

                                     Iterator it = soapHeader

                                                        .extractHeaderElements(SOAPConstants.URI_SOAP_1_2_ROLE_NEXT);

 

                                     if (it == null || !it.hasNext())

                                               generateSoapFault(soapMessage,

                                                                 "No Header block for role next");

 

                                     Node node = (Node) it.next();

 

                                     String value = node == null ? null : node.getValue();

 

                                     if (value == null)

                                               generateSoapFault(soapMessage,

                                                                 "No authation info in header blocks");

 

                                     String[] infos = value.split("&");

 

                                     return authValidate(infos[0], infos[1]);

 

                            } catch (SOAPException e) {

                                     e.printStackTrace();

                            }

 

                   }

                   return false;

         }

         private boolean authValidate(String userName, String password) {

                   if (userName == null || password == null) {

                            return false;

                   }

 

                   if ("admin".equals(userName) && "admin".equals(password)) {

                            return true;

                   }

                   return false;

         }

 

         private void generateSoapFault(SOAPMessage soapMessage, String reasion) {

                   try {

                            SOAPBody soapBody = soapMessage.getSOAPBody();

                            SOAPFault soapFault = soapBody.getFault();

 

                            if (soapFault == null) {

                                     soapFault = soapBody.addFault();

                            }

 

                            soapFault.setFaultString(reasion);

 

                            throw new SOAPFaultException(soapFault);

 

                   } catch (SOAPException e) {

                            // TODO Auto-generated catch block

                            e.printStackTrace();

                   }

         }

 

}

上面这段代码看似很长,其实逻辑很简单,注意:

publicboolean handleMessage(SOAPMessageContext context)这个方法。

Handler会先检查,这个soap是in还是out,当然,对于我们来说要验证客户端提交上来的用户名和密码,因该是in。

因此,如果这个soap是in,并且含有soapheader(我们的用户名密码是含在soap header中的,可不是通过url以http://xxx.xxx.xxx/xxx.do?username=xxx&password=xxx这样的形式传输的哦,这样做是彻头彻尾的作弊,不对的作法,和掩耳盗铃没啥区别),并且含有soap header,这个soap header中会提取出“username&password”这样的一个字符串,然后进行用户名和密码的比对与校验。


1.2handler类的XML描述

我们有了Handler类,还需要有一个handler的xml文件,对该类进行描述,这个xml文件和handler类放在同一层java的package下,该XML名为:handlers.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">

    <handler-chain>

        <handler>

            <handler-name>authHandler</handler-name>

             <handler-class>

ctsjavacoe.ws.fromjava.AuthValidationHandler

</handler-class>

        </handler>

    </handler-chain>

</handler-chains> 

二、书写Webservice并引用handler

2.1 接口

package ctsjavacoe.ws.fromjava;

import javax.jws.WebMethod;

import javax.jws.WebService;

import javax.jws.soap.SOAPBinding;

import javax.jws.soap.SOAPBinding.Style;

@WebService

@SOAPBinding(style = Style.RPC)

public interface AuthorServer {

         @WebMethod

         public String sayHello(String name);

}

2.2 实现类

package ctsjavacoe.ws.fromjava;

 

import javax.jws.HandlerChain;

import javax.jws.WebService;

@WebService(endpointInterface = "ctsjavacoe.ws.fromjava.AuthorServer")

@HandlerChain(file = "handlers.xml")

public class AuthorServerImpl implements AuthorServer {

         public String sayHello(String name) {

                   return "Hello: " + name;

         }

}

核心是这一行:@HandlerChain(file= "handlers.xml")。

把它编译成webservice,然后发布工程到tomcat中去吧。

得到wsdl: http://localhost:8080/JaxWSSample/AuthorServerService?wsdl

我们用SOAPUI来调用这个webservice试试效果:

大家可以看到入到的output是:<faultstring>No Header blockfor role next</faultstring>

三、书写客户端

根据wsdl先得到相关的stub。

3.1 书写client端的handler类

package ctsjavacoe.ws.fromjava;

import java.util.Set;

import javax.xml.namespace.QName;

import javax.xml.soap.*;

import javax.xml.ws.handler.MessageContext;

import javax.xml.ws.handler.soap.SOAPHandler;

import javax.xml.ws.handler.soap.SOAPMessageContext;

public class ClientAuthenticationHandler implements SOAPHandler<SOAPMessageContext> {

         public Set<QName> getHeaders() {

                   // TODO Auto-generated method stub

                   return null;

         }

         public void close(MessageContext arg0) {

                   // TODO Auto-generated method stub

         }

         public boolean handleFault(SOAPMessageContext arg0) {

                   // TODO Auto-generated method stub

                   return false;

         }

         public boolean handleMessage(SOAPMessageContext ctx) {

                   Boolean request_p = (Boolean) ctx

                                     .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

 

                   if (request_p) {

                            try {

                                     SOAPMessage msg = ctx.getMessage();

                                     SOAPEnvelope env = msg.getSOAPPart().getEnvelope();

                                     SOAPHeader hdr = env.getHeader();

 

                                     if (hdr == null)

                                               hdr = env.addHeader();

 

                                     QName qname_user = new QName("http://fromjava.ws.ctsjavacoe/",

                                                        "AuthorServerImplService");

                                     SOAPHeaderElement helem_user = hdr.addHeaderElement(qname_user);

                                     helem_user.setActor(SOAPConstants.URI_SOAP_1_2_ROLE_NEXT);

                                     helem_user.addTextNode("admin&admin1");

                                     msg.saveChanges();

                                     //msg.writeTo(System.out);

                                     return true;

                            } catch (Exception e) {

                                     e.printStackTrace();

                            }

                   }

                   return false;

         }

}

该handler类主要的核心方法为:

public booleanhandleMessage(SOAPMessageContext ctx)方法

该方法中需要注意的是:

QName qname_user = new QName("http://fromjava.ws.ctsjavacoe/",

                                                        "AuthorServerImplService");

SOAPHeaderElement helem_user = hdr.addHeaderElement(qname_user);

helem_user.setActor(SOAPConstants.URI_SOAP_1_2_ROLE_NEXT);

helem_user.addTextNode("admin&admin1");

msg.saveChanges();

我们通过上述的语句就已经知道我们会在客户端传过去一对用户名与密码,它们是:

username=admin

password=admin1

3.2 书写客户端

package ctsjavacoe.ws.fromjava;

 

import java.util.*;

 

import javax.xml.ws.handler.Handler;

import javax.xml.ws.handler.HandlerResolver;

import javax.xml.ws.handler.PortInfo;

public class AuthorServerClient {

         public static void main(String[] args) {

                   AuthorServerImplService service = new AuthorServerImplService();

                   service.setHandlerResolver(new HandlerResolver() {

                            public List<Handler> getHandlerChain(PortInfo arg0) {

                                     List<Handler> handlerList = new ArrayList<Handler>();

                                     handlerList.add(new ClientAuthenticationHandler());

                                     return handlerList;

                            }

                   });

                   AuthorServer authorService = service.getAuthorServerImplPort();

                   String msg = authorService.sayHello("MK");

                   System.out.println("rtn msg=====" + msg);

         }

}

 

 


四、运行上述例子后出错啦?为什么?

运行后我们得到了如下的输出:


出错了?为什么?

我们回过头来看两个handler,一个是server端的handler,其中:

if ("admin".equals(userName) && "admin".equals(password)) {

                            return true;

         }

一个是client的handler类,其中:

helem_user.addTextNode("admin&admin1");

啊。。。因为server端的密码要求是”admin”不是”admin1”,于是我们把client端的密码也改成”admin”,再次运行我们的客户端,得到输出:

完成第二天的教程



目录
相关文章
|
移动开发 安全 网络安全
|
安全 数据安全/隐私保护 前端开发
WebService 简单安全验证
原文:WebService 简单安全验证         最近新接了一个需要调用第三方WebService的项目,看到这个第三方WebService被调用的时候,需要授权用户名和密码,于是自己也想对WebService的安全授权这个方面进行了一下研究,以前调用的WebService大部分都是局域网内部调用,几乎没有什么权限需要增加的,今天借此机会,深入研究了一下,发现实现起来还是挺容易的。
1481 0
|
Web App开发 存储 安全
使用WSE实现Web Service安全----我的第一篇
原文: 使用WSE实现Web Service安全----我的第一篇 WSE(Web Services Enhancements)是微软为了使开发者通过.NET创建出更强大,更好用的Web Services而推出功能增强插件。
1317 0
|
Java Maven 网络架构
简单的Jax-WS WebService实现
目录   1       定义Service 2       服务端发布Service 2.1      排除WebService中的某个方法 3       客户端访问Service 4       java2ws工具的使用 4.
986 0
|
Web App开发 安全 Shell
通向架构师的道路(第十四天)Axis2 Web Service安全之rampart
一、加密保护我们的web service传输 在上一天的教程中,我们讲了一个简单的基于” security-constraint”的以指定用户名和密码来保护一个Web Service以及如何用https对这个web service的通讯过程进行保护。
1168 0
|
Web App开发 安全 应用服务中间件
通向架构师的道路(第十三天)Axis2 Web Service安全初步
一、WSSecurity简述 安全的Web服务是Web服务成功的必要保证。但大家都知道,Web服务使用XML来进行数据交换,而XML在默认情况下是明文编码的;同时,大部分Web服务使用HTTP协议作为传输协议,同样,HTTP也是使用明文方式来传输数据的。
1164 0
|
安全 Java 网络架构
jax-ws之webservice security(安全)教程第一天
前言: 在前面的“5天学会jaxws-webservice教程”,我们讲了基本的jax-ws的使用。 Jax-ws是业界公认的标准的webservice,它已经成为了一个行业界标准,包括cxf,其实cxf也是调用的jax-ws为标准的基于spring的webservice框架。
1103 0
|
Web App开发 安全 网络性能优化
jax-ws之webservice security(安全)教程第三天
前言: 在今天的学习中,我们讲开始过渡到一个真正的websecurity例子。 第二天中我们知道了如何使用handler来处理客户端提交上来的用户名与密码,而在今天的学习中,我们将会使用服务端预先配置的用户名与密码来authenticate客户端提交上来的值。
1416 0
|
7月前
|
缓存 应用服务中间件 数据库
Python Web Service开发及优化
随着互联网的快速发展,Web服务已成为现代技术的核心。Python作为一种功能强大且易于学习的编程语言,在Web服务开发领域占据着重要地位。Python Web服务开发的重要性在于它能够提供高效、可扩展且易于维护的解决方案。本篇博客将探讨如何使用Python的Flask框架、Gunicorn WSGI服务器和Nginx网页服务器来实现高性能的Web服务。