當前位置:學問君>人在職場>IT認證>

如何創建安全的Web Service

學問君 人氣:1.6W

我們在使用Web Service的過程中,很多情況是需要對web service請求做認證的,對於執行在web容器裏的應用程序來說,可能會比較簡單一些,通常可以透過filter來做一些處理,但是其實CXF本身也提供了對web service認證的方式。

如何創建安全的Web Service

1. 首先是一個簡單pojo

package com.googlecode.garbagecan.cxfstudy.security;

public class User {

private String id;

private String name;

private String password;

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

}

2. Web Service接口

package com.googlecode.garbagecan.cxfstudy.security;

import java.util.List;

import javax.jws.WebMethod;

import javax.jws.WebResult;

import javax.jws.WebService;

@WebService

public interface UserService {

@WebMethod

@WebResult List list();

}

3. Web Service實現類

package com.googlecode.garbagecan.cxfstudy.security;

import java.util.ArrayList;

import java.util.List;

public class UserServiceImpl implements UserService {

public List list() {

List users = new ArrayList();

for (int i = 0; i < 10; i++) {

User user = new User();

user.setId("" + i);

user.setName("user_" + i);

user.setPassword("password_" + i);

users.add(user);

}

return users;

}

}

4. Server端Handler,其中使用了一個Map來存放用戶資訊,真是應用中可以使用數據庫或者其它方式獲取用戶和密碼

package com.googlecode.garbagecan.cxfstudy.security;

import java.io.IOException;

import java.util.HashMap;

import java.util.Map;

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 ServerUsernamePasswordHandler implements CallbackHandler {

// key is username, value is password

private Map users;

public ServerUsernamePasswordHandler() {

users = new HashMap();

users.put("admin", "admin");

}

public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

WSPasswordCallback callback = (WSPasswordCallback) callbacks[0];

String id = callback.getIdentifier();

if (users.containsKey(id)) {

if (!callback.getPassword().equals(users.get(id))) {

throw new SecurityException("Incorrect password.");

}

} else {

throw new SecurityException("Invalid user.");

}

}

}

5. Client端Handler,用來設定用戶密碼,在真實應用中可以根據此類和下面的.測試類來修改邏輯設定用戶名和密碼。

package com.googlecode.garbagecan.cxfstudy.security;

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 ClientUsernamePasswordHandler implements CallbackHandler {

public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

WSPasswordCallback callback = (WSPasswordCallback) callbacks[0];

int usage = callback.getUsage();

System.out.println("identifier: " + callback.getIdentifier());

System.out.println("usage: " + callback.getUsage());

if (usage == WSPasswordCallback.USERNAME_TOKEN) {

callback.setPassword("admin");

}

}

}

6. 單元測試類,注意在Server端添加了WSS4JInInterceptor到Interceptor列表中,在Client添加了WSS4JOutInterceptor到Interceptor列表中。

package com.googlecode.garbagecan.cxfstudy.security;

import java.net.SocketTimeoutException;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import javax.xml.ws.WebServiceException;

import junit.framework.Assert;

import org.apache.cxf.endpoint.Client;

import org.apache.cxf.endpoint.Endpoint;

import org.apache.cxf.frontend.ClientProxy;

import org.apache.cxf.interceptor.LoggingInInterceptor;

import org.apache.cxf.interceptor.LoggingOutInterceptor;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

import org.apache.cxf.transport.http.HTTPConduit;

import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;

import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;

import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;

import org.apache.ws.security.WSConstants;

import org.apache.ws.security.handler.WSHandlerConstants;

import org.junit.BeforeClass;

import org.junit.Test;

public class UserServiceTest {

private static final String address = "http://localhost:9000/ws/security/userService";

@BeforeClass

public static void setUpBeforeClass() throws Exception {

JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();

factoryBean.getInInterceptors().add(new LoggingInInterceptor());

factoryBean.getOutInterceptors().add(new LoggingOutInterceptor());

Map props = new HashMap();

props.put("action", "UsernameToken");

props.put("passwordType", "PasswordText");

props.put("passwordCallbackClass", ServerUsernamePasswordHandler.class.getName());

WSS4JInInterceptor wss4JInInterceptor = new WSS4JInInterceptor(props);

factoryBean.getInInterceptors().add(wss4JInInterceptor);

factoryBean.setServiceClass(UserServiceImpl.class);

factoryBean.setAddress(address);

factoryBean.create();

}

@Test

public void testList() {

JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean();

factoryBean.setAddress(address);

factoryBean.setServiceClass(UserService.class);

Object obj = factoryBean.create();

Client client = ClientProxy.getClient(obj);

Endpoint endpoint = client.getEndpoint();

Map props = new HashMap();

props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);

props.put(WSHandlerConstants.USER, "admin");

props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);

props.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientUsernamePasswordHandler.class.getName());

WSS4JOutInterceptor wss4JOutInterceptor = new WSS4JOutInterceptor(props);

endpoint.getOutInterceptors().add(wss4JOutInterceptor);

HTTPConduit conduit = (HTTPConduit) client.getConduit();

HTTPClientPolicy policy = new HTTPClientPolicy();

policy.setConnectionTimeout(5 * 1000);

policy.setReceiveTimeout(5 * 1000);

conduit.setClient(policy);

UserService service = (UserService) obj;

try {

List users = service.list();

Assert.assertNotNull(users);

Assert.assertEquals(10, users.size());

} catch(Exception e) {

if (e instanceof WebServiceException

&& e.getCause() instanceof SocketTimeoutException) {

System.err.println("This is timeout exception.");

} else {

e.printStackTrace();

}

}

}

}

最後執行上面的測試類來測試結果,也可以修改測試方法中的密碼,看看錯誤結果。

TAGS:Service Web