Saturday, September 25, 2004

Struts: Synchronizer Token Pattern

Synchronizer Token Pattern digunakan untuk mengatasi masalah multiple/duplicate submit pada suatu halaman yang memiliki form input.

Submit berulang-ulang pada suatu halaman dari form input biasanya terjadi karena sengaja atau tidak sengaja. Dengan sengaja misalnya user mencoba melakukan posting berkali-kali dengan data yang sama atau secara tidak sengaja misalnya user meng-click tombol submit berkali-kali atau melakukan refresh pada halaman setelah dia post/submit dari halaman form input. Kedua kasus tersebut tentu saja tidak diharapkan, untuk itu kita perlu melakukan trik untuk dapat mencegah terjadinya multiple submit tersebut.

Salah satu solusinya adalah dengan menggunakan Synchronizer Token Pattern, caranya dengan memberikan suatu tanda (token) untuk setiap transaksi (aksi submit dari user). Transaksi dimulai ketika web server akan menampilakan halaman form input. Form input tersebut diberi tanda dengan varibel tersembunyi (hidden input) dengan nilai tertentu biasanya nomor random. Nilai tersebut disimpan di server dalam session milik user. Ketika user melakukan submit pada form, server akan mencocokan nilai token yang dikirim dari form dengan yang ada di session user. Jika nilai tersebut sama maka server akan melanjutkan proses dan me-reset kembali nilai token dan menyimpannya kembali di session user. Jika kedua nilai tersebut berbeda berarti user mengirimkan data yang berbeda dari yang diharapkan server, artinya server akan me-reject data yang dikirim oleh user.

Dengan Struts, kita dapat mengimplementasikan Synchonizer Pattern dengan mudah. Sebelum halaman dengan form input dipanggil, pada action panggilah saveToken(request) untuk menbuat nilai token baru dan menyimpannya di session. Halaman form tidak perlu penambahan apa2, hanya pastikan form yang digunakan menggunakan tag <html:form>. Dengan cara seperti itu form akan memiliki input dengan tipe hidden yang otomatis dibuat oleh struts:


<input name="org.apache.struts.taglib.html.TOKEN" value="d3977d02b2490a92e6f8f22e8a0777b4" type="hidden">

Sedangkan pada action pemroses dari form tersebut kita lakukan pengecekan token sbb:

public ActionForward deleteQuotation(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {

ActionErrors errors = new ActionErrors();
ActionMessages messages = new ActionMessages();

// Check if token is valid
if (!isTokenValid(request)) {
errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.transaction"));
saveErrors(request, errors);
return mapping.findForward("transactionError");
}

try {
// Call business proces here
...

// Reset token
resetToken(request);

messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("msg.FooSuccess"));
saveMessages(request, messages);
} catch (Exception e) {
e.printStackTrace();
errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error", e.getMessage()));
}
if (!errors.isEmpty()) {
saveErrors(request, errors);
}
return mapping.findForward("submitSuccess");
}

No comments:

Followers