ApacheCXF框架API实现了WS-Security协议,其中包括xml签名、用户令牌、时间戳等;
实现目标:在SOAP WebService的服务端实现客户端身份认证、时间戳形式的安全机制;(密钥加密及签名方式认证待续)
运行环境:apache-cxf-3.1.6、jdk1.7、tomcat7.0.68
cxf框架和spring高度集成,示例安全机制服务端基于spring框架,客户端调用可以使用或不使用spring框架;
对于客户端用户密码验证主要通过cxf框架的WSS4J拦截器实现,base64加密、解密过程本身由框架实现,用户只需要在服务端和客户端的拦截器实现方法中设置原始的用户名密码即可。
客户端发出请求前(请求出)拦截设置加密密码,服务端接收(请求入)后拦截解密验证密码。
服务端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>cxfjaxwssecurityserver1</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/beans.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <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> <session-config> <session-timeout>60</session-timeout> </session-config> </web-app>
服务端spring bean配置:
<?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"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/bindings/soap
http://cxf.apache.org/schemas/configuration/soap.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath*:META-INF/cxf/cxf-extension-*.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
<bean id="saajIn" class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
<bean id="mypasswdcallback" class="cxf.jaxws.basic.server.PasswdCallback"/>
<bean id="wss4jin" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken Timestamp"></entry>
<entry key="passwordType" value="PasswordDigest"/>
<entry key="passwordCallbackRef" >
<ref bean="mypasswdcallback"/>
</entry>
</map>
</constructor-arg>
</bean>
<jaxws:endpoint id="bookinfoservice" address="/bookinfo" implementor="cxf.jaxws.basic.server.BookServiceImpl" >
<jaxws:outInterceptors>
<ref bean="logOut"/>
</jaxws:outInterceptors>
<jaxws:inInterceptors>
<ref bean="logIn"/>
<ref bean="saajIn"/>
<ref bean="wss4jin"/>
</jaxws:inInterceptors>
</jaxws:endpoint>
</beans>
服务端拦截器:
public class PasswdCallback implements CallbackHandler {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback ) callbacks[0];
if(pc.getIdentifier().equals("administrator")){
pc.setPassword("merrick");
}else{
System.err.println("Password verified failed.");
}
}
}
Webservice接口类、实现类、实体类:
@WebService( name="BookService", portName="BookServicePort")
public interface BookService {
@WebMethod
public String getOneBookInfo(DTOBean param);
@WebMethod BookEntity getBookinfoEntity(DTOBean param);
}
public class BookServiceImpl implements BookService {
@Resource
WebServiceContext wsContext;
@Override
public String getOneBookInfo(DTOBean param) {
String bookinfo = "<<A Tale of two citiest>>,2001,English";
System.out.println("---Invoking getOneBookInfo, DTOBean: "+ param.getId() + "," + param.getName());
return bookinfo;
}
@Override
public BookEntity getBookinfoEntity(DTOBean param) {
BookEntity be = new BookEntity();
be.setAuthor("Mark Twen");
be.setFirstpub("1778");
be.setName("Tom's house");
System.out.println("---Invoking getBookinfoEntity, DTOBean: "+ param.getId() + "," + param.getName());
return be;
}
}
public class BookEntity {
String name;
String author;
String firstpub;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getFirstpub() {
return firstpub;
}
public void setFirstpub(String firstpub) {
this.firstpub = firstpub;
}
}
客户端拦截器:
public class ClientPasswdCallback implements CallbackHandler {
private Map<String,String> passwds = new HashMap<String,String>();
public ClientPasswdCallback() {
passwds.put("administrator", "merrick");
}
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {//交给wss4j API去加密(ws-security的实现,用户令牌验证)
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback wsp = (WSPasswordCallback)callbacks[i];
String pas = passwds.get(wsp.getIdentifier());
if(pas!=null){
wsp.setPassword(pas);
return;
}
}
}
}
WebService 客户端调用(无框架方式、spring方式)(客户端略):
(webservice客户端可根据WebService的wsdl url,采用cxf的wsdl2java工具生成)
public static void clientwith_UserTokenAuth() throws Throwable {//success
/**
* 带用户令牌验证的客户端
* Spring配置
* **/
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "autoclient/test/client2.xml" });
// BookServiceImplService sv = new BookServiceImplService(u);
BookService client = (BookService) context.getBean("client");
DtoBean b = new DtoBean();
b.setId(1);
b.setName("a");
//
String response = client.getOneBookInfo(b);
System.out.println("Response: " + response);
BookEntity response2 = client.getBookinfoEntity(b);
System.out.println("Response: " + response2.getAuthor() + ", " + response2.getName() +", "+ response2.getFirstpub());
}
/***无框架方式*/
public static void clientwith_UserTokenAuth_withoutSpring() throws Throwable {//success
Map<String, Object> outProps = new HashMap<String, Object>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN +" "+ WSHandlerConstants.TIMESTAMP);//令牌+时间戳
outProps.put(WSHandlerConstants.USER, "administrator" );
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST );
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, "autoclient.test.ClientPasswdCallback");
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(cxfclient.jaxws.auto.BookService.class);
// 设置ws访问地址
factory.setAddress("http://localhost:8080/cxfjaxwssecurityserver1/services/bookinfo");
factory.getOutInterceptors().add(new WSS4JOutInterceptor(outProps));
//addAll(list);
cxfclient.jaxws.auto.BookService service = (cxfclient.jaxws.auto.BookService) factory.create();
DtoBean b = new DtoBean();
b.setId(1);
b.setName("a");
String response = service.getOneBookInfo(b);
System.out.println(response);
}
客户端安全机制带框架方式调用,spring配置:
<?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/bindings/soap
http://cxf.apache.org/schemas/configuration/soap.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
<bean id="saajOut" class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
<bean id="wss4jout" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken Timestamp" />
<entry key="passwordType" value="PasswordDigest" />
<entry key="user" value="administrator" />
<entry key="passwordCallbackClass" value="autoclient.test.ClientPasswdCallback"/>
</map>
</constructor-arg>
</bean>
<jaxws:client id="client"
serviceClass="cxfclient.jaxws.auto.BookService"
address="http://localhost:8080/cxfjaxwssecurityserver1/services/bookinfo">
<jaxws:inInterceptors>
<ref bean="logIn"/>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<ref bean="logOut"/>
<ref bean="saajOut"/>
<ref bean="wss4jout"/>
</jaxws:outInterceptors>
</jaxws:client>
</beans>
相关推荐
3. **用户身份验证**:支持多种身份验证机制,如用户名令牌、X.509令牌和SAML令牌,确保只有经过认证的用户才能访问服务。 4. **时间戳**:添加时间戳到SOAP消息中,防止重放攻击,确保消息的新鲜性。 5. **密钥...
在“webservice-cxf-签名认证”这个实例中,重点是WS-Security,它提供了一种在SOAP消息层添加安全功能的方法。签名认证是WS-Security的一个关键组成部分,用于确保消息的完整性和来源的可信性。以下是如何实现这一...
这样,每次通过客户端代理调用Web Service时,都会自动添加预设的SOAP Header,从而实现身份验证和其他自定义功能。请注意,实际项目中需要替换`your_username`和`your_password`为真实的用户名和密码。同时,为了...
6. **安全协议**:如WS-Security(Web Services Security)、WS-Trust和WS-Federation,它们提供了在SOAP消息中添加安全头来实现上述安全特性的标准框架。 在"Server"部分的源码中,可能会看到实现这些安全特性的...
除了身份验证,SoapHeader还可用于实现其他安全功能,比如角色授权、消息签名、时间戳等。通过结合不同的SoapHeader,我们可以构建出一套全面的安全机制,保护Web服务免受非法访问和攻击。 总结来说,“WebService...
CXF实现了WS-Security,允许开发者添加数字签名、加密、时间戳等安全元素到SOAP消息中。 5. **Token-based认证**:OAuth、JWT(JSON Web Tokens)等令牌机制也是常见的安全策略。CXF可以与这些标准配合,实现基于...
WSS4J,全称是Web Services Security for Java,是由Apache软件基金会开发的一个开源库,主要专注于实现Web服务安全标准,尤其是WS-Security规范。这个规范定义了如何在SOAP消息中添加安全信息,如数字签名、加密等...
在Web服务中,安全认证是验证客户端请求的身份的过程,以确保只有授权的用户或系统可以访问服务。在CXF中,我们可以使用WS-Security(Web Services Security)标准来实现这一功能,它支持多种安全机制,如用户名令牌...
常见的安全措施包括SSL/TLS加密、数字签名确保消息完整性、WS-Security标准提供身份验证和授权等。 总结,WebService是实现跨平台数据交换和同步的重要技术,它利用XML、SOAP、WSDL和UDDI等标准,构建起服务提供者...
5. **X.509证书认证**: 使用X.509证书进行客户端和服务端的身份验证。 **三、CxfSpringWss4JServer** 这个服务器端项目包含了Spring-CXF-WSS4J集成的核心配置和实现。主要步骤包括: 1. **配置WSS4J安全策略**: ...