前面我们说到CXF添加内置的拦截器,今天的话,我们来讲下如何添加自定义拦截器;
我们的实例是客户端访问服务端webservice接口要加权限认证。
我们思路先说下。我们可以通过在SOAP消息的Header头信息中添加自定义信息,然后发送到服务端端,服务器端通过获取
Header头消息,然后进行认证;这里的添加消息,和获取消息认证,我们都是通过自定义拦截器来实现;
OK下面我们来实现下:
首先是服务器端:
我们自定义拦截器:MyInterceptor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
package com.java1234.interceptor;
import java.util.List;
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;
/** * 自定义拦截器
* @author Administrator
*
*/
public class MyInterceptor extends AbstractPhaseInterceptor<SoapMessage>{
public MyInterceptor(){
// 在调用方法之前调用拦截器
super (Phase.PRE_INVOKE);
}
/**
* 拦截获取消息
*/
public void handleMessage(SoapMessage message) throws Fault {
List<Header> headers=message.getHeaders();
if (headers== null || headers.size()== 0 ){
throw new Fault( new IllegalArgumentException( "没有Header,拦截器实施拦截" ));
}
Header firstHeader=headers.get( 0 );
Element ele=(Element) firstHeader.getObject();
NodeList userIds=ele.getElementsByTagName( "userName" );
NodeList userPasses=ele.getElementsByTagName( "password" );
if (userIds.getLength()!= 1 ){
throw new Fault( new IllegalArgumentException( "用户名格式不对" ));
}
if (userPasses.getLength()!= 1 ){
throw new Fault( new IllegalArgumentException( "密码格式不对" ));
}
String userId=userIds.item( 0 ).getTextContent();
String userPass=userPasses.item( 0 ).getTextContent();
if (!userId.equals( "java1234" ) || ! userPass.equals( "123456" )){
throw new Fault( new IllegalArgumentException( "用户名或者密码不正确" ));
}
}
} |
这里的话,我们主要是获取Header头消息,然后获取userName和password节点,然后获取值,进行权限判断,假如认证不通过,我们抛出异常;
在Server类里,我们要添加一个in 拦截器,在进入的时候,我们要进行验证;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.java1234.webservice;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import com.java1234.interceptor.MyInterceptor;
import com.java1234.webservice.impl.HelloWorldImpl;
public class Server {
public static void main(String[] args) {
System.out.println( "web service start" );
HelloWorld implementor = new HelloWorldImpl();
String address = "http://10.10.7.18/helloWorld" ;
JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();
factoryBean.setAddress(address); // 设置暴露地址
factoryBean.setServiceClass(HelloWorld. class ); // 接口类
factoryBean.setServiceBean(implementor); // 设置实现类
factoryBean.getInInterceptors().add( new LoggingInInterceptor()); // 添加in拦截器 日志拦截器
factoryBean.getOutInterceptors().add( new LoggingOutInterceptor()); // 添加out拦截器
factoryBean.getInInterceptors().add( new MyInterceptor()); // 添加自定义拦截器
factoryBean.create();
System.out.println( "web service started" );
}
} |
接下来是修改客户端代码:
我们同样要添加一个自定义拦截器:AddHeaderInterceptor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
package com.java1234.interceptor;
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;
public class AddHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
private String userName;
private String password;
public AddHeaderInterceptor(String userName, String password) {
super (Phase.PREPARE_SEND); // 发送SOAP消息之前调用拦截器
this .userName=userName;
this .password=password;
}
public void handleMessage(SoapMessage message) throws Fault {
List<Header> headers=message.getHeaders();
Document doc=DOMUtils.createDocument();
Element ele=doc.createElement( "authHeader" );
Element idElement=doc.createElement( "userName" );
idElement.setTextContent(userName);
Element passElement=doc.createElement( "password" );
passElement.setTextContent(password);
ele.appendChild(idElement);
ele.appendChild(passElement);
headers.add( new Header( new QName( "java1234" ),ele));
}
} |
这里的话,我们主要是在拦截器里创建头消息;
Client类里我们要修改下,加下Out 拦截器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
package com.java1234.webservice;
import java.util.List;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import com.java1234.interceptor.AddHeaderInterceptor;
public class Client {
public static void main(String[] args) {
HelloWorldService service= new HelloWorldService();
HelloWorld helloWorld=service.getHelloWorldPort();
org.apache.cxf.endpoint.Client client=ClientProxy.getClient(helloWorld);
// client.getInInterceptors().add(new LoggingInInterceptor()); // 添加in拦截器 日志拦截器
client.getOutInterceptors().add( new AddHeaderInterceptor( "java1234" , "123456" )); // 添加自定义拦截器
client.getOutInterceptors().add( new LoggingOutInterceptor()); // 添加out拦截器
//System.out.println(helloWorld.say("java1234"));
/*User user=new User();
user.setUserName("jack");
user.setPassword("123456");
List<Role> roleList=helloWorld.getRoleByUser(user);
for(Role role:roleList){
System.out.println(role.getId()+","+role.getRoleName());
}*/
MyRoleArray array=helloWorld.getRoles();
List<MyRole> roleList=array.item;
for ( int i= 0 ;i<roleList.size();i++){
MyRole my=roleList.get(i);
System.out.print(my.key+ ":" );
for (Role r:my.value){
System.out.print(r.getId()+ "," +r.getRoleName()+ " " );
}
System.out.println();
}
}
} |
OK这样就完整了自定义拦截器实现权限认证;
先运行Server类,和以前一样;
假如我们把 client.getOutInterceptors().add(new AddHeaderInterceptor("java1234","123456")); // 添加自定义拦截器
密码改成 123
然后运行Client类,会报错;
用户名或者密码不正确;
完整代码: http://pan.baidu.com/s/1dEaHNcX