WebService CXF学习(高级篇3):WS-Security

这一节我们来探讨一下WebService安全问题,如果所有系统都运行在一个封闭的局域网内,那么可以不考虑网络攻击,拒绝服务,消息篡改,窃取等问题。但通常情况都接入互联网,那么我就得考虑信息安全问题,像前面那样直接将消息裸传,肯定不行。那么,我们就得给消息加密。CXF可以结合WSS4J来对消息安全进行管理,可以使用令牌,X.509认证对消息头或内容进行加密。这节我只对令牌加密做一个简单的描述,我们还以Demo的形式来讲解一下。
    这个Demo是在CXF+Spring+Hibernate的基础修改而成。在这里我只针对修改的东西进行讲解。
Java代码 
<?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"  
    xsi:schemaLocation="   
        http://www.springframework.org/schema/beans    
        http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   
        http://cxf.apache.org/jaxws    
        http://cxf.apache.org/schemas/jaxws.xsd">   
    <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" />   
  
  
    <jaxws:endpoint id="service"  
        implementor="com.itdcl.service.ServiceImpl" address="/Service">   
        <jaxws:inInterceptors>   
            <bean   
                class="org.apache.cxf.interceptor.LoggingInInterceptor" />   
            <bean   
                class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />   
            <bean   
                class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">   
                <constructor-arg>   
                    <map>   
                        <entry key="action" value="UsernameToken" />   
                        <entry key="passwordType"  
                            value="PasswordText" />   
                        <entry key="user" value="cxfServer" />   
                        <entry key="passwordCallbackRef">   
                            <ref bean="serverPasswordCallback" />   
                        </entry>   
                    </map>   
                </constructor-arg>   
            </bean>   
        </jaxws:inInterceptors>   
    </jaxws:endpoint>   
  
    <bean id="serverPasswordCallback"  
        class="com.itdcl.ws.ServerPasswordCallback" />   
  
</beans>  

<?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"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
		http://cxf.apache.org/jaxws 
		http://cxf.apache.org/schemas/jaxws.xsd">
	<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" />


	<jaxws:endpoint id="service"
		implementor="com.itdcl.service.ServiceImpl" address="/Service">
		<jaxws:inInterceptors>
			<bean
				class="org.apache.cxf.interceptor.LoggingInInterceptor" />
			<bean
				class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
			<bean
				class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
				<constructor-arg>
					<map>
						<entry key="action" value="UsernameToken" />
						<entry key="passwordType"
							value="PasswordText" />
						<entry key="user" value="cxfServer" />
						<entry key="passwordCallbackRef">
							<ref bean="serverPasswordCallback" />
						</entry>
					</map>
				</constructor-arg>
			</bean>
		</jaxws:inInterceptors>
	</jaxws:endpoint>

	<bean id="serverPasswordCallback"
		class="com.itdcl.ws.ServerPasswordCallback" />

</beans>


    action:UsernameToken指使用用户令牌
    passwordType:PasswordText指密码加密策略,这里直接文本
    user:cxfServer指别名
    passwordCallBackRef:serverPasswordCallback指消息验证

    消息验证类:
Java代码 
package com.itdcl.ws;   
  
import java.io.IOException;   
  
import javax.security.auth.callback.Callback;   
import javax.security.auth.callback.CallbackHandler;   
import javax.security.auth.callback.UnsupportedCallbackException;   
  
import org.apache.ws.security.WSPasswordCallback;   
  
public class ServerPasswordCallback implements CallbackHandler {   
  
    public void handle(Callback[] callbacks) throws IOException,   
            UnsupportedCallbackException {   
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];   
        String pw = pc.getPassword();   
        String idf = pc.getIdentifier();   
        System.out.println("password:"+pw);   
        System.out.println("identifier:"+idf);   
        if (pw.equals("josen") && idf.equals("admin")) {   
            // 验证通过   
        } else {   
            throw new SecurityException("验证失败");   
        }   
    }   
  
}  

package com.itdcl.ws;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class ServerPasswordCallback implements CallbackHandler {

	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
		String pw = pc.getPassword();
		String idf = pc.getIdentifier();
		System.out.println("password:"+pw);
		System.out.println("identifier:"+idf);
		if (pw.equals("josen") && idf.equals("admin")) {
			// 验证通过
		} else {
			throw new SecurityException("验证失败");
		}
	}

}


     消息验证类通过实现CallbackHandler接口,实现handle方法来进行用户认证。

     那么,客户端又怎样来验证消息是否确呢。
Java代码 
<?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"  
    xsi:schemaLocation="   
        http://www.springframework.org/schema/beans    
        http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   
        http://cxf.apache.org/jaxws    
        http://cxf.apache.org/schemas/jaxws.xsd">   
  
    <jaxws:client id="service"  
        address="http://localhost:9999/cxf/Service"  
        serviceClass="com.itdcl.service.IService">   
        <jaxws:outInterceptors>   
            <bean   
                class="org.apache.cxf.interceptor.LoggingOutInterceptor" />   
            <bean   
                class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />   
            <bean   
                class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">   
                <constructor-arg>   
                    <map>   
                        <entry key="action" value="UsernameToken" />   
                        <entry key="passwordType"  
                            value="PasswordText" />   
                        <entry key="user" value="cxfClient" />   
                        <entry key="passwordCallbackRef">   
                            <ref bean="clientPasswordCallback" />   
                        </entry>   
                    </map>   
                </constructor-arg>   
            </bean>   
        </jaxws:outInterceptors>   
    </jaxws:client>   
  
    <bean id="clientPasswordCallback"  
        class="com.itdcl.ws.ClientPasswordCallback" />   
</beans>  

<?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"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
		http://cxf.apache.org/jaxws 
		http://cxf.apache.org/schemas/jaxws.xsd">

	<jaxws:client id="service"
		address="http://localhost:9999/cxf/Service"
		serviceClass="com.itdcl.service.IService">
		<jaxws:outInterceptors>
			<bean
				class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
			<bean
				class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
			<bean
				class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
				<constructor-arg>
					<map>
						<entry key="action" value="UsernameToken" />
						<entry key="passwordType"
							value="PasswordText" />
						<entry key="user" value="cxfClient" />
						<entry key="passwordCallbackRef">
							<ref bean="clientPasswordCallback" />
						</entry>
					</map>
				</constructor-arg>
			</bean>
		</jaxws:outInterceptors>
	</jaxws:client>

	<bean id="clientPasswordCallback"
		class="com.itdcl.ws.ClientPasswordCallback" />
</beans>


    客户端在发送SOAP时对消息对认证,策略跟服务端一样。但是认证类有所区别:
Java代码 
package com.itdcl.ws;   
  
import java.io.IOException;   
  
import javax.security.auth.callback.Callback;   
import javax.security.auth.callback.CallbackHandler;   
import javax.security.auth.callback.UnsupportedCallbackException;   
  
import org.apache.ws.security.WSPasswordCallback;   
  
public class ClientPasswordCallback implements CallbackHandler {   
  
    public void handle(Callback[] callbacks) throws IOException,   
            UnsupportedCallbackException {   
        for(int i=0;i<callbacks.length;i++)   
        {   
             WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];   
             pc.setPassword("josen");   
             pc.setIdentifier("admin");   
        }   
    }   
  
}  

package com.itdcl.ws;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class ClientPasswordCallback implements CallbackHandler {

	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		for(int i=0;i<callbacks.length;i++)
        {
             WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
             pc.setPassword("josen");
             pc.setIdentifier("admin");
        }
	}

}


     客户端在发送消息,设置好用户名和密码。服务端用相应的用户名和密码进行验证。

你可能感兴趣的:(java,apache,webservice,互联网,Security)