Axis1 webservice security with wss4j

Web Service สามารถถูกเรียกได้จากคนที่รู้จัก WSDL ของเรา เพราะฉะนั้นเราจึงต้องทำการจำกัดสิทธิให้เฉพาะคนที่เราอนุญาตเท่านั้น ซึ่งวิธีการทำ Web Service Security ก็มีหลายวิธี วิธีที่ง่ายที่สุดคือ Username Token

ในตอนที่แล้ว https://magickiat.wordpress.com/2014/05/22/upload-file-with-apache-axis1/ ผมได้สร้าง web service สำหรับ upload file และผมจะทำให้ web service ตัวนี้เรียกได้เฉพาะคนที่มี account ที่ผมระบุเท่านั้น

เครื่องมือที่ใช้


เหมือนตอนที่แล้วเลยครับ แค่เพิ่ม lib ของ http://ws.apache.org/wss4j/index.html แต่มีข้อแม้ว่าต้องใช้ version 1.5.x นะครับ โดยโหลดได้จาก http://archive.apache.org/dist/ws/wss4j/
สรุปว่า lib ที่ผมใช้ต้องเพิ่มดังนี้

  • wss4j-1.5.12.jar
  • xmlsec-1.4.3.jar

คำเตือน: โปรดระวังเรื่อง version ด้วย

ลงมือฝั่ง Server


  1. เพิ่ม lib เข้าไปใน WEB-INF/lib
  2. เปิดไฟล์ server-config.wsdd แล้วไปที่บรรทัด ns1:service name=”Upload”
    service name=Upload
    แล้วเพิ่มคำสั่งนี้ในบรรทัดข้างล่าง

    <ns1:requestFlow>
       <ns1:handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
        <ns1:parameter name="passwordCallbackClass" value="ws.SecureCallback"/>
        <ns1:parameter name="action" value="UsernameToken"/>
       </ns1:handler>
      </ns1:requestFlow>
    
  3. เพิ่มคลาส Callback เพื่อเป็นการระบุว่า Username ไหนใช้ Password อะไร (ตอนใช้งานจริง password ควรจะเข้ารหัส)
    เพื่อนำไปตรวจสอบกับ Client ที่ส่งเข้ามา

    ซึ่งวิธีที่ง่ายที่สุดก็คือ Fix ไว้ทั้ง Username และ Password แล้วเอาไปให้ Client ที่เราต้องการให้ส่งค่านั้นๆ เข้ามาเลย เพื่อสะดวกในการจัดการ Account

    package 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 SecureCallback implements CallbackHandler {
    
    	@Override
    	public void handle(Callback[] callbacks) throws IOException,
    			UnsupportedCallbackException {
    		for (int i = 0; i < callbacks.length; i++) {
    
    			if (callbacks[i] instanceof WSPasswordCallback) {
    				WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
    				if ("someuser".equals(pc.getIdentifier())) {
    					pc.setPassword("S3cr3t");
    				}
    			} else {
    				throw new UnsupportedCallbackException(callbacks[i],
    						"Unrecognized Callback");
    			}
    		}
    	}
    }
    
  4. ทำการ Start Server แล้วเรียก URL ของ WSDL หากไม่พบ Erro ถือว่าผ่าน

ลงมือฝั่ง Client


  1. ในตอนนี้หาก Client ทำงานก็จะพบ Error ว่าไม่มี Security header
    ws client error Security header
  2. ให้เพิ่ม lib 2 ตัวที่โหลดมาเข้าไปใน build path
  3. สร้างไฟล์ client_deploy.wsdd ไว้ข้างนอกสุด
    client_deploy.wsdd
    และเพิ่มโค้ดนี้เข้าไป

    <deployment xmlns="http://xml.apache.org/axis/wsdd/"
    	xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
    
    	<transport name="http"
    		pivot="java:org.apache.axis.transport.http.HTTPSender" />
    
    	<globalConfiguration>
    		<requestFlow>
    			<handler type="java:org.apache.ws.axis.security.WSDoAllSender">
    				<parameter name="action" value="UsernameToken" />
    				<parameter name="user" value="someuser" />
    				<parameter name="passwordCallbackClass" value="client.PWCallback" />
    				<parameter name="passwordType" value="PasswordDigest" />
    			</handler>
    		</requestFlow>
    	</globalConfiguration>
    
    </deployment>
    
  4. เพิ่มคลาส Callback เพื่อเป็นการระบุ Username และ Password ที่ได้จาก Server
    package client;
    
    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 PWCallback implements CallbackHandler {
    
    	@Override
    	public void handle(Callback[] callbacks) throws IOException,
    			UnsupportedCallbackException {
    		for (int i = 0; i < callbacks.length; i++) {
    			if (callbacks[i] instanceof WSPasswordCallback) {
    				WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
    				if ("someuser".equals(pc.getIdentifier())) {
    					pc.setPassword("S3cr3t");
    				}
    			} else {
    				throw new UnsupportedCallbackException(callbacks[i],
    						"Unrecognized Callback");
    			}
    		}
    	}
    }
    
  5. แก้ไข App.java เพื่อ load config ดังนี้
    package client;
    
    import java.io.File;
    import java.io.IOException;
    import java.rmi.RemoteException;
    
    import javax.xml.rpc.ServiceException;
    
    import org.apache.axis.EngineConfiguration;
    import org.apache.axis.configuration.FileProvider;
    import org.apache.commons.io.FileUtils;
    
    import ws.Upload;
    import ws.UploadServiceLocator;
    
    public class App {
    
    	public static void main(String[] args) {
    		try {
    			String uploadFilepath = "E:/workspace/data.txt";
    			
    			EngineConfiguration config = new FileProvider("client_deploy.wsdd");
    			Upload service = new UploadServiceLocator(config).getUpload();
    			
    			boolean status = service.upload(FileUtils.readFileToByteArray(new File(uploadFilepath)));
    			
    			System.out.println("Upload file complete: " + status);
    			
    		} catch (ServiceException e) {
    			e.printStackTrace();
    		} catch (RemoteException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		
    	}
    
    }
    
    
  6. เมื่อรันโปรแกรมก็จะสามารถเรียกใช้งาน web service ได้ตามปกติ
    client calll secure ws
  7. ทดลองเปลี่ยน password ของ client ที่ไม่ตรงกับ Server ก็จะพบกับข้อความว่าไม่ได้รับอนุญาตให้ใช้งาน
    client call secure ws with wrong password

One thought on “Axis1 webservice security with wss4j

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s