webserive学习记录5-拦截器完成登陆校验

Posted liunianfeiyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webserive学习记录5-拦截器完成登陆校验相关的知识,希望对你有一定的参考价值。

  说说cxf中的拦截器,可以分为系统拦截器(如日志拦截器)和自定义拦截器,也可以分为出拦截器和入拦截器,也可以分为服务器拦截器和客户端拦截器。

  下面将实现一个可以进行登陆验证的拦截器,其中用户名作为方法参数传递,密码放在发送给服务器的xml的header中。

  服务端

  代码结构如下:

技术分享图片

 

  ValidUser:

技术分享图片

  applicationContext

技术分享图片

  CXFServices

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
	xmlns:soap="http://cxf.apache.org/bindings/soap"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd  
            http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd">

	<!-- 1.使用jaxws:endpoint标签的配置发布一个 webservice 2.用implementor属性配置服务提供实现类 
		3.address属性配置外部访问的相对路径 4.使用 jaxws:inInterceptors 标签配置2个日志拦截器,用来打印调用时的日志信息 
		5.注意:在此配置文件中,需加入jaxws与soap命名空间 -->
		
	<!-- <import resource="classpath*:META-INF/cxf/cxf.xml" /> 
	<import resource="classpath*:META-INF/cxf/cxf-extension-soap.xml" />  
	<import resource="classpath*:META-INF/cxf/cxf-servlet.xml" />	 -->
	
	<bean id="jaxWsServiceFactoryBean" class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean">
		<property name="wrapped" value="true" />
	</bean>
		
	<jaxws:endpoint id="loginCheckService"
		implementor="login.check.ws.impl.LoginCheck" address="/loginCheck">
		<jaxws:inInterceptors>
			<bean id="inLoggingInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
			<bean id="outLoggingInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
			<bean id="loginCheckInterceptor" class="login.check.ws.impl.LoginCheck" />
		</jaxws:inInterceptors>
		<jaxws:serviceFactory>
			<ref bean="jaxWsServiceFactoryBean" />
		</jaxws:serviceFactory>
	</jaxws:endpoint>

</beans>  

  web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
   <display-name>logincheckws</display-name>
   <welcome-file-list>
     <welcome-file>index.html</welcome-file>
     <welcome-file>index.htm</welcome-file>
     <welcome-file>index.jsp</welcome-file>
     <welcome-file>default.html</welcome-file>
     <welcome-file>default.htm</welcome-file>
     <welcome-file>default.jsp</welcome-file>
   </welcome-file-list>
  
   <!-- 加入spring -->  
   <context-param>  
     <param-name>contextConfigLocation</param-name>  
     <param-value>classpath:applicationContext*.xml</param-value>  
   </context-param>  
   <listener>  
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
   </listener>  
  
  <!-- 加入CXF支持 -->  
   <servlet>  
        <description>Apache CXF Endpoint</description>  
        <display-name>cxf</display-name>  
        <servlet-name>cxf</servlet-name>  
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>  
        <load-on-startup>1</load-on-startup>  
    </servlet>  
    <servlet-mapping>  
        <servlet-name>cxf</servlet-name>  
        <url-pattern>/services/*</url-pattern>  
    </servlet-mapping>
    
</web-app>

  LoginCheck:继承了AbstractPhaseInterceptor,实现了handleMessage方法,用来从客户端发来soap消息头中获取密码,并会保存在ThreadLocal变量中,供校验用户时使用。

package login.check.ws.impl;

import java.util.List;

import javax.jws.WebService;
import javax.xml.namespace.QName;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import login.check.constant.ValidUser;
import login.check.ws.interf.ILoginCheck;

@WebService(endpointInterface="login.check.ws.interf.ILoginCheck", targetNamespace="http://login.check.ws")
public class LoginCheck extends AbstractPhaseInterceptor<SoapMessage> implements ILoginCheck{

	private static final ThreadLocal<String> passwords = new ThreadLocal<>();
	
	public LoginCheck() {
		super(Phase.PRE_PROTOCOL);
	}

	@Override
	public boolean checkUser(String username) {
		return ValidUser.validUser.get(username).equals(passwords.get());
	}

	@Override
	public void handleMessage(SoapMessage message) throws Fault {
		List<Header> headers = message.getHeaders();
		if(headers == null || headers.size() == 0)
		{
			throw new Fault(new RuntimeException("无密码信息"));
		}
		
		Element passwordEle = null;

		for(Header header: headers)
		{
			QName qName = header.getName();
			String nameSpace = qName.getNamespaceURI();
			String tagName = qName.getLocalPart();
			
			if(nameSpace != null && nameSpace.equals("http://login.check.ws.password") && tagName != null)
			{
				passwordEle = (Element)header.getObject();
				break;
			}
		}
		
		if(null == passwordEle)
		{
			throw new Fault(new RuntimeException("无密码信息"));
		}
		
		NodeList passwordList = passwordEle.getElementsByTagName("password");
		
		if(passwordList == null || passwordList.getLength() != 1)
		{
			throw new Fault(new RuntimeException("密码信息错误"));
		}
		
		passwords.set(passwordList.item(0).getTextContent());
	}

}

   客户端

  首先是生成客户端代码,在此不在赘述,

    技术分享图片

 

  然后自定义一个拦截器,向soap消息头中写入密码信息,这里密码的获取也用到的ThreadLocal变量,在测试类中将密码存入ThreadLocal变量中,然后在拦截器中就可以获取到密码了。

  拦截器代码如下:

package login.check.ws.client;

import java.util.List;

import javax.xml.namespace.QName;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import login.check.ws.test.LoginTest;

public class PasswordInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

	public PasswordInterceptor() {
		super(Phase.PREPARE_SEND);
	}

	@Override
	public void handleMessage(SoapMessage message) throws Fault {
		List<Header> headers = message.getHeaders();
		Document doc = DOMUtils.createDocument();
		
		Element passwordNS = doc.createElementNS("http://login.check.ws.password", "loginCheck");
		Element password = doc.createElement("password");
		password.setTextContent(LoginTest.password.get());
		
		passwordNS.appendChild(password);
		
		headers.add(new Header(new QName("loginCheck"), passwordNS));
	}

}

   测试代码如下:

技术分享图片

  使用了三个拦截器并将密码存入了ThreadLocal中,

  测试结果如下:

技术分享图片

   代码地址:https://files.cnblogs.com/files/liunianfeiyu/logincheckwebservice.rar

以上是关于webserive学习记录5-拦截器完成登陆校验的主要内容,如果未能解决你的问题,请参考以下文章

AngularJs HTTP响应拦截器实现登陆权限校验

JAVAEE——BOS物流项目03:学习计划messagermenubutton登陆拦截器信息校验和取派员添加功能

JAVAEE——struts2_04:自定义拦截器struts2标签登陆功能和校验登陆拦截器的实现

webserive学习记录3-eclipse创建webservice

webserive学习记录6-页面请求webservice

webserive学习记录4-获取天气的例子