4.6Webservice
发布时间:2020-12-16 21:50:05 所属栏目:安全 来源:网络整理
导读:个人印象笔记 在Web工程中发布Webservice WebService的安全设置即webservice的头部消息处理 Handler处理链的使用 1:在Web工程中发布Webservice: 1.1方法一: 先建一个Web工程,然后把要发布的Webservice的接口和实现类拷到Web工程的一个包下,并且 在接口类
个人印象笔记
在Web工程中发布Webservice
WebService的安全设置即webservice的头部消息处理
Handler处理链的使用
1:在Web工程中发布Webservice:
1.1方法一:
先建一个Web工程,然后把要发布的Webservice的接口和实现类拷到Web工程的一个包下,并且
在接口类前加上
@SOAPBinding(style = SOAPBinding.Style.RPC)。
再写一个监听器,用来发布Webservice的,它会在工程启动的时候,自动发布我们的Webserice服务。
(建立监听器的步骤:建一个java类且实现ServletContextListener,然后实现contextInitialized()和contextDestroyed这两个函数,最后要在web.xml中配置 <listener><listener-class>com.listener.PublishServiceListener</listener-class></listener>)。
注意:这时候有个问题,就是当我们访问的时候,如果我们访问的是Webservice里的方法,就得访问
http://localhost:7070/first,
如果我们访问的方法是部署在Tomcat下的方法,就得访问
http://localhost:8080这个地址。
这样有个麻烦就是我们得记住两个端口号。
监听器的代码:
package com.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.xml.ws.Endpoint;
import com.webservice.First;
/**
?* 用于发布WebService
?*
?* @author ctd
?*
?*/
public class PublishServiceListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("工程初始化的操作");
/**
* 发布WebService
*/
Endpoint.publish("http://localhost:7070/first",new First());
System.out.println("通过WEB的方式发布Fist服务成功");
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
?????System.out.println("工程销毁的操作");
}
}
客户端调用类:
package com.test;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
public class TestMain {
public static void main(String[] args) {
TestMain.callServlet();
TestMain.callService();
}
private static void callServlet() {
DefaultHttpClient httpClient = new DefaultHttpClient();
String url = "http://localhost:8080/WebService_Server_04/servlet/TestServlet";
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
System.out.println("enity = " + entity);
String responseStr = EntityUtils.toString(entity);
System.out.println(responseStr);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void callService() {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://localhost:7070/first?wsdl");
try {
StringBuffer soapXML = new StringBuffer();
soapXML
.append("<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">");
soapXML.append("<SOAP-ENV:Header/>");
soapXML.append("<SOAP-ENV:Body>");
soapXML.append("<ns:add xmlns:ns="http://webservice.com/">");//这里的命名空间要和你自己的对应
soapXML.append("<x>11</x>");
soapXML.append("<y>55</y>");
soapXML.append("</ns:add>");
soapXML.append("</SOAP-ENV:Body>");
soapXML.append("</SOAP-ENV:Envelope>");
StringEntity soapEntity = new StringEntity(soapXML.toString());
httpPost.setEntity(soapEntity);
httpPost.setHeader("Content-Type","text/xml; charset=UTF-8");
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
String str = EntityUtils.toString(entity);
//System.out.println("str = " + str);
String addResult = str.substring(str.indexOf("<addResult>") + 11,
str.indexOf("</addResult>"));
System.out.println("addResult = " + addResult);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
1.2方法二:
服务端:
Webservice和Web工程是合在一起的。
步骤:
? ? ?这时要建立一个Web Service Project (optional Maven support)(不选加入Maven)工程,写一个Servlet类,运行看是否可以正常运行。然后建一个包名叫sss.webservice,在这个包里写一个实现类Login类,当要发布这个类的时候,右击这个包,选择New Web Service,然后根据自己的情况选择Strategy(假设选第二个),点击下一步。等到完成时,会生成一个代理类(
这个代理类才是WebService.Web service不一定要用接口,只是推荐使用接口而已.)和一个WSDL文件和Sun-jaxws.xml,然后Web.xml里会多了这些东西:
? //WSServlet这个类是帮助我们在Web工程中发布Web service的时候用到的
? //它最主要的任务是发布webservice
<servlet>
<servlet-name>PubSerivceServlet</servlet-name>
<servlet-class>
com.sun.xml.ws.transport.http.servlet.WSServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>PubSerivceServlet</servlet-name>
<url-pattern>/LoginPort</url-pattern>
</servlet-mapping>
注意:其中
com.sun.xml.ws.transport.http.servlet.WSServlet 这个类jdk里是没有的,所以得自己加jar包
就是
导入了myeclipse 的两个libraries就可以了,步骤:
工程上右键-》properties-》java build path -》 add libraries -》 选myeclipse libraries -》next 拉到最后选择最后两个库(jax-ws runtime 和 jax-ws api)。
最后像平常发布Web工程那样发布就好了,访问正常的Servlet还是和平常一样,访问Webservice时,后面得加
/LoginPort?这个(
<url-pattern>/LoginPort</url-pattern>)。
前面说的这些,主要是解决两个端口变为一个端口的问题而已,这两种方式都可以用。
客户端调用:和平常的类似。
2、WebService的安全设置即webservice的头部消息处理
3种方案
? ? ?2.1名称/密码 直接定义在方法中。(String content,String userid,String password);(最常用)
? ? ?2.2名称/密码 不定义在方法中。 (Soap消息,分为head和body):
? ? ? ? ? ? ?? ?????2.2.1:放在显示的header消息中
? ? ? ? ? ? ?? ?????2.2.2:放在隐示的header消息中
2.1:直接定义在方法上:
? ? ?建工程名叫webservice06,在里面建一个包,在包里建一个实现类叫header_one,实现代码如下:
package sss.webservice;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.Gson;
import com.util.JdbcUtil;
public class Header_One {
public static Map<String,String> systemMap = new HashMap<String,String>();
static {
systemMap.put("OA","222221");
systemMap.put("CRM","222222");
systemMap.put("ERP","33333");
}
public String login(String username,String password,
String systemIdentity,String systemToken) {
if ((systemIdentity == null || systemIdentity.equals(""))
|| (systemToken == null || systemToken.equals(""))) {
throw new RuntimeException("服务端异常:系统标识与系统令牌不能为空 ");
} else {
if (systemMap.containsKey(systemIdentity) == false) {
throw new RuntimeException("服务端异常:没有该系统标识 ");
} else {
String tempToken = systemMap.get(systemIdentity);
if (systemToken.equals(tempToken) == false) {
throw new RuntimeException("服务端异常:令牌与系统不匹配 ");
} else {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
String sql = null;
Map<String,Object> jsonMap = new HashMap<String,Object>();
try {
sql = "Select user_name,user_pw From T_user where user_name = ?";
conn = JdbcUtil.getConnection();
stmt = conn.prepareStatement(sql);
stmt.setString(1,username);
rs = stmt.executeQuery();
if (rs.next()) {
String db_password = rs.getString("user_pw");
if (password.equals(db_password)) {
jsonMap.put("flag",true);
} else {
jsonMap.put("flag",false);
jsonMap.put("errorMsg","密码不正确");
}
} else {
jsonMap.put("flag","用户名不正确");
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("服务端异常 = " + e.getMessage());
} finally {
}
Gson gson = new Gson();
String jsonStr = gson.toJson(jsonMap);
return jsonStr;
}
}
}
}
}
然后按照上面的方法二,在web工程中结合webservice的方法写好服务端。在客户端呢,就利用wsdl地址来生成客户端,并写测试类就好了。
服务端接口:
package com.webservice;
import javax.jws.WebParam;
import javax.jws.WebResult;
@javax.jws.WebService(targetNamespace = "http://webservice.com/",serviceName = "Header_OneService",portName = "Header_OnePort")
public class Header_OneDelegate {
com.webservice.Header_One header_One = new com.webservice.Header_One();
@WebResult(name = "loginResult")
public String login(@WebParam(name = "username")
String username,@WebParam(name = "password")
String password,@WebParam(name = "systemIdentity")
String systemIdentity,@WebParam(name = "systemToken")
String systemToken) {
return header_One
.login(username,password,systemIdentity,systemToken);
}
}
客户端测试:
package com.webservice_client.header_one;
import javax.xml.ws.soap.SOAPFaultException;
public class TestMain {
public static void main(String[] args) {
HeaderOneDelegate headerOne = new HeaderOneService().getHeaderOnePort();
try {
String jsonStr = headerOne.login("admin","123","OA","222221");
System.out.println(jsonStr);
} catch (SOAPFaultException e) {
System.out.println(e.getMessage());
}
}
}
?2.2.1:放在显示的header消息中
服务端的实现类和上面的Header_One是一样的,生成的接口类也是一样的,只是在参数要放在header里的@webparam里加了Header = true;代码如下:
public class Header_TwoDelegate {
com.webservice.Header_Two header_Two = new com.webservice.Header_Two();
@WebResult(name = "loginResult")
public String login(@WebParam(name = "username")
String username,@WebParam(name = "password")
String password,@WebParam(name = "systemIdentity",header = true)
String systemIdentity,@WebParam(name = "systemToken",header = true)
String systemToken) {
return header_Two
.login(username,systemToken);
}
}
然后发布和客户端生成,都和上面的是一样的。只是测试类有所不同:
package com.webservice_client.header_two;
//客户端测试类
public class TestMain {
public static void main(String[] args) {
HeaderTwoDelegate twoService = new HeaderTwoService()
.getHeaderTwoPort();
Login parameters = new Login();
parameters.setUsername("admin");
parameters.setPassword("123");
LoginResponse loginResponse = twoService.login(parameters,"CRM",
"222222");
String jsonStr = loginResponse.loginResult;
System.out.println(jsonStr);
}
}
此外,生成的wsdl文件也有不同之处,详情请自己去比较吧!
?2.2.2:放在隐示的header消息中:
? ? ?2.2.2.1在此之前先讲一个
Handler的建立与使用(与过滤器和监听器类似)。
? ? ?步骤:在上面的工程中,新建一个包叫com.webservice.handler,在里面建一个
PrintMessageHandler类,这个类得实现SOAPHandler<SOAPMessageContext>接口,重载它的方法。代码如下:
package com.webservice.handler;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class PrintMessageHandler implements SOAPHandler<SOAPMessageContext> {
public Set<QName> getHeaders() {
System.out.println("getHeaders方法...");
return null;
}
public void close(MessageContext arg0) {
System.out.println("close方法...");
}
public boolean handleFault(SOAPMessageContext arg0) {
System.out.println("handleFault方法...");
return false;
}
public boolean handleMessage(SOAPMessageContext context) {
? System.out.println("handleMessage方法....");
return false;
}
}
然后写一个名叫server_chain.xml的东西,里面的内容为
<?xml version="1.0" encoding="UTF-8"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<javaee:handler-chain>
<javaee:handler>
<javaee:handler-class>
? com.webservice.handler.PrintMessageHandler
</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>
最后服务端要用这个处理类,就在接口类前写上@HandlerChain(file = "../../server_chain.xml")。客户端要用处理类,就得把这个写在实现类前。
?2.2.2.2:
package com.webservice;
//实现类,和前面的是一样的。
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.Gson;
import com.util.JdbcUtil;
public class Header_Three {
public String login_xx(String username,String password) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
String sql = null;
Map<String,Object>();
try {
sql = "Select username,password From T_Userinfo where username = ?";
conn = JdbcUtil.getConn();
stmt = conn.prepareStatement(sql);
stmt.setString(1,username);
rs = stmt.executeQuery();
if (rs.next()) {
String db_password = rs.getString("password");
if (password.equals(db_password)) {
jsonMap.put("flag",true);
} else {
jsonMap.put("flag",false);
jsonMap.put("errorMsg","密码不正确");
}
} else {
jsonMap.put("flag","用户名不正确");
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("服务端异常 = " + e.getMessage());
} finally {
JdbcUtil.closeResource(rs,stmt,conn);
}
Gson gson = new Gson();
String jsonStr = gson.toJson(jsonMap);
return jsonStr;
}
}
生成的webservice是:因为要用到处理类,所有手动加了
@HandlerChain(file = "../../server_chain.xml")
package com.webservice;
import javax.jws.HandlerChain;
import javax.jws.WebParam;
@javax.jws.WebService(targetNamespace = "http://webservice.com/",serviceName = "Header_ThreeService",portName = "Header_ThreePort")
@HandlerChain(file = "../../server_chain.xml")
public class Header_ThreeDelegate {
com.webservice.Header_Three header_Three = new com.webservice.Header_Three();
public String login_xx(@WebParam(name = "username")
String username,@WebParam(name = "password")
String password) {
return header_Three.login_xx(username,password);
}
}
服务端处理类的代码:
package com.webservice.handler;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.rpc.soap.SOAPFaultException;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class PrintMessageHandler implements SOAPHandler<SOAPMessageContext> {
public static Map<String,"33333");
}
public Set<QName> getHeaders() {
System.out.println("getHeaders方法...");
return null;
}
public void close(MessageContext arg0) {
System.out.println("close方法...");
}
public boolean handleFault(SOAPMessageContext arg0) {
System.out.println("handleFault方法...");
return false;
}
public boolean handleMessage(SOAPMessageContext context) {
System.out.println("handleMessage方法...");
Boolean is_out = (Boolean) context
.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (is_out == true) {
System.out.println("服务端返回消息:");
} else {
System.out.println("服务端接收消息:");
}
SOAPMessage message = context.getMessage();
try {
message.writeTo(System.out);
System.out.println("");
System.out.println("");
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
/**
* 处理消息
*/
if (is_out == false) {
SOAPEnvelope envelope;
try {
envelope = message.getSOAPPart().getEnvelope();
SOAPHeader header = envelope.getHeader();
SOAPBody body = envelope.getBody();
SOAPFault fault = body.getFault();
if (fault == null) {
fault = body.addFault();
}
System.out.println(header);
NodeList nodeList = header.getElementsByTagName("checkinfo");
if (nodeList == null || nodeList.getLength() == 0) {
System.out.println("checkinfo为空");
fault.setFaultCode("500");
fault.setFaultString("Header中的checkinfo节点为空值");
throw new javax.xml.ws.soap.SOAPFaultException(fault);
} else {
Element checkinfo = (Element) nodeList.item(0);
String systemIdentity = checkinfo.getElementsByTagName(
"systemIdentity").item(0).getFirstChild()
.getNodeValue();
String systemToken = checkinfo.getElementsByTagName(
"systemToken").item(0).getFirstChild()
.getNodeValue();
System.out.println("systemIdentity = " + systemIdentity);
System.out.println("systemToken = " + systemToken);
if (systemMap.containsKey(systemIdentity) == false) {
fault.setFaultCode("500");
fault.setFaultString("checkinfo中systemIdentity不正确");
throw new javax.xml.ws.soap.SOAPFaultException(fault);
} else {
String db_value = systemMap.get(systemIdentity);
if (db_value.equals(systemToken) == false) {
fault.setFaultCode("500");
fault.setFaultString("checkinfo中验证令牌不正确");
throw new javax.xml.ws.soap.SOAPFaultException(
fault);
} else {
return true;
}
}
}
} catch (SOAPException e) {
e.printStackTrace();
}
}
return true;
}
}
客户端:
测试类代码:
package com.webservice_client.header_three;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import sun.awt.windows.ThemeReader;
public class TestMain {
public static void main(String[] args) {
// TestMain.HttpClient_SendHeader();
TestMain.ClientStub_SendHeader();
}
/**
* 通过客户端桩的方式来发送,这时就需要用到ClientHeaderChain这个处理链
*/
private static void ClientStub_SendHeader() {
HeaderThreeDelegate threeService = new HeaderThreeService()
.getHeaderThreePort();
String jsonStr = threeService.loginXx("admin","123");
System.out.println(jsonStr);
}
/**
* 通过HttpClient来发送Soap中的Header消息
*/
private static void HttpClient_SendHeader() {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(
"http://localhost:8080/WebService_Server_06/Header_ThreeService?wsdl");
try {
StringBuffer soapXML = new StringBuffer();
soapXML
.append("<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservice.com/">");
soapXML.append("<soapenv:Header>");
soapXML.append("<checkinfo>");
soapXML.append("<systemIdentity>OA</systemIdentity>");
soapXML.append("<systemToken>222221</systemToken>");
soapXML.append("</checkinfo>");
soapXML.append("</soapenv:Header>");
soapXML.append("<soapenv:Body>");
soapXML.append("<web:login_xx>");
soapXML.append("<username>admin</username>");
soapXML.append("<password>1111</password>");
soapXML.append("</web:login_xx>");
soapXML.append("</soapenv:Body>");
soapXML.append("</soapenv:Envelope>");
StringEntity soapEntity = new StringEntity(soapXML.toString());
httpPost.setEntity(soapEntity);
httpPost.setHeader("Content-Type","text/xml; charset=UTF-8");
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
String str = EntityUtils.toString(entity);
System.out.println("str = " + str);
if (str.indexOf("<faultcode>") != -1) {
/**
* 说明有错误消息
*/
String faultcode = str.substring(
str.indexOf("<faultcode>") + 11,str
.indexOf("</faultcode>"));
String faultstring = str.substring(
str.indexOf("<faultstring>") + 13,str
.indexOf("</faultstring>"));
System.out.println("faultCoe = " + faultcode);
System.out.println("faultstring = " + faultstring);
} else {
/**
* 正确
*/
String result = str.substring(str.indexOf("<return") + 17,str
.indexOf("</return>"));
System.out.println("result = " + result);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端用到的处理类代码:建处理类的步骤如上。
package com.webservice_client.header_three;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class ClientHeaderChain implements SOAPHandler<SOAPMessageContext> {
/**
* 客户端要加入checkinfo的头部消息,供服务端解析
*/
public boolean handleMessage(SOAPMessageContext context) {
Boolean is_out = (Boolean) context
.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (is_out == true) {
/**
* 加入Header消息
*/
SOAPMessage message = context.getMessage();
try {
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
SOAPBody body = envelope.getBody();
SOAPHeader header = envelope.getHeader();
if (header == null) {
header = envelope.addHeader();
}
QName checkinfo = new QName("http://webservice.com/",
"checkinfo");
SOAPHeaderElement checkInfoElement = header
.addHeaderElement(checkinfo);
checkInfoElement.addChildElement("systemIdentity").setValue(
"CRM");
checkInfoElement.addChildElement("systemToken").setValue("222222");
} catch (SOAPException e) {
e.printStackTrace();
}
}
return true;
}
public Set<QName> getHeaders() {
return null;
}
public void close(MessageContext arg0) {
}
public boolean handleFault(SOAPMessageContext arg0) {
// TODO Auto-generated method stub
return false;
}
}
注意点:
? ? ?比较合理的方式。通过SoapHandler来传递与接收头部消息。
?????抛异常不能使用throw new RuntimeException的方式,要使用throw new SOAPFaultException(fault);
? ?? 从服务端角度看:inbound表示接收客户端消息,outbound表示响应消息给客户端..从客户端角度看时正好与之相反
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- Angular2 @Componet 装饰器基础知识
- Bootstrap实现登录校验表单(带验证码)
- 郁闷
- angularjs – Angular promise在函数内解析但不在外部
- 重新加载页面提供了AngularJS HTML5模式的错误GET请求
- 如何用参数创建bash别名?
- Scalac发现错误:scala.Boolean(false)required:java.lang
- 在Angular2 Dart中设置Router和RouterLink的正确方法是什么
- angularjs – 在Angular UI-Router的动态视图中添加一个SEO
- angular中出现错误的提示指令[ng:areq]的原因