Wednesday, April 8, 2009

Simple JAAS Example

Dalam 2 entry sebelumnya saya sudah tahu bagaimana caranya mengimplementasikan policy & permission, serta Subject dan Principal. Sekarang bagaimana mengimplementasikannya di JAAS untuk membentuk sebuah sistem security sederhana?

Seperti kepanjangannya, JAAS digunakan untuk autentifikasi dan autorisasi. Autentifikasi adalah proses yang memastikan bahwa user 'yang mengaku sebagai scott' adalah benar 'scott' yang dimaksud oleh sistem kita. Agar bisa diautentifikasi, user 'yang mengaku sebagai scott' harus memasukkan credential, biasanya berupa username dan password, untuk dicocokkan dengan data user scott yang kita miliki. Pada JAAS, sebuah interface bernama CallbackHandler digunakan untuk mendapatkan data-data credential tersebut dari user, dan sebuah interface LoginModule digunakan untuk melakukan autentifikasi (masih ingat method LoginModule.commit() pada entry sebelumnya?).

Sedangkan autorisasi adalah proses untuk memastikan bahwa user yang sudah sukses diautentifikasi sebelumnya hanya dapat mengakses resource yang berhak diaksesnya saja. Subject.doAsPrivileged adalah method yang digunakan untuk tujuan ini.

Sekarang akan kita lihat implementasi CallbackHandler dan LoginModule serta bagaimana memanggilnya dari aplikasi kita :

public class SimpleCallbackHandler implements CallbackHandler{
private String name;
private String password;

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;
}

public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i <>
Callback callback = callbacks[i];
if (callback instanceof NameCallback) {
NameCallback nameCB = (NameCallback) callback;
nameCB.setName(name);
} else if (callback instanceof PasswordCallback) {
PasswordCallback passwordCB = (PasswordCallback) callback;
passwordCB.setPassword(password.toCharArray());
}
}
}
}

public class SimpleLoginModule implements LoginModule {
private Subject subject;
private CallbackHandler callbackHandler;
private String name;
private String password;

public boolean abort() throws LoginException {
...
}

public boolean commit() throws LoginException {
if ("scott".equals(name)) {
Principal p = new SysAdminPrincipal(name);
subject.getPrincipals().add(p);
return true;
} else if ("matt".equals(name)) {
Principal p = new UserPrincipal(name);
subject.getPrincipals().add(p);
return true;
} else {
return false;
}
}

public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
this.callbackHandler = callbackHandler;
this.subject = subject;
}

public boolean login() throws LoginException {
NameCallback nameCB = new NameCallback("Username");
PasswordCallback passwordCB = new PasswordCallback("Password", false);
Callback[] callbacks = new Callback[] { nameCB, passwordCB };
try {
callbackHandler.handle(callbacks);
} catch (IOException e) {
e.printStackTrace();
LoginException ex = new LoginException("IOException logging in.");
ex.initCause(e);
throw ex;
} catch (UnsupportedCallbackException e) {
String className = e.getCallback().getClass().getName();
LoginException ex = new LoginException(className + " is not a supported Callback.");
ex.initCause(e);
throw ex;
}
name = nameCB.getName();
password = String.valueOf(passwordCB.getPassword());
if ("scott".equals(name) && "tiger".equals(password)) {
// login in scott
return true;
} else if ("matt".equals(name) && "butterfly".equals(password)) {
// login in matt
return true;
} else {
return false;
}
}

public boolean logout() throws LoginException {
...
}
}

dan berikut adalah main method untuk melakukan autentifikasi dan autorisasi

public static void main(String[] args) {
policyFile = new File("file:/root/workspace/JAAS/config/security.policy");

testAccess("scott", "tiger");
testAccess("matt", "butterfly");
}

private static void testAccess(final String username, String password) {
SimpleCallbackHandler cb = new SimpleCallbackHandler();
cb.setName(username);
cb.setPassword(password);

// ambil login context dari configuration file untuk ambil login module mana yg diload
LoginContext ctx = null;
try {
ctx = new LoginContext("SimpleLoginContext", cb);
ctx.login();
} catch(Exception e) {
e.printStackTrace();
}

// jika login sukses maka bisa didapatkan subjectnya
Subject subject = ctx.getSubject();
System.out.println("Logged in " + subject);
// Create privileged action block which limits permissions to only the Subject's permissions.
try {
Subject.doAsPrivileged(subject, new PrivilegedAction() {
public Object run() {
policyFile.canRead();
System.out.println(username + " can access Policy file.");
return null;
}
}, null);
} catch (SecurityException e) {
System.out.println(username + " can NOT access Policy file.");
} catch(Exception e) {
}
}

Seperti terlihat pada method testAccess(), di sana hanya ada CallbackHandler yang dimasukkan sebagai parameter LoginContext, tidak tampak SimpleLoginModule sebagai implementasi LoginModule. Lalu bagaimana keduanya berhubungan? Selain mempunyai parameter CallbackHandler, LoginContext di atas mempunyai satu parameter lagi yaitu "SimpleLoginContext". SimpleLoginContext berada pada file konfigurasi yang akan kita buat yaitu jazz.config :

SimpleLoginContext
{
edu.mat.jaas.SimpleLoginModule REQUIRED;
};

Sekarang terlihat jelas di situlah LoginModule yang kita cari berada. Dan sekarang setelah proses autentifikasi selesai, saatnya melakukan autorisasi melalui

Subject.doAsPrivileged(subject, new PrivilegedAction() {
public Object run() {
policyFile.canRead();
System.out.println(username + " can access Policy file.");
return null;
}
}, null);

Seperti contoh pada entry sebelumnya, kita perlu membuat file policy yang berisi

grant Principal edu.mat.jaas.UserPrincipal "matt"
{
// not granted anything
};

grant Principal edu.mat.jaas.SysAdminPrincipal "scott"
{
permission java.io.FilePermission "file:/root/workspace/JAAS/config/security.policy", "read";
};

grant codeBase "file:/root/workspace/JAAS/build/*"
{
permission javax.security.auth.AuthPermission "modifyPrincipals";
permission javax.security.auth.AuthPermission "modifyPublicCredentials";
permission javax.security.auth.AuthPermission "modifyPrivateCredentials";
permission javax.security.auth.AuthPermission "createLoginContext.*";
permission javax.security.auth.AuthPermission "doAs";
permission javax.security.auth.AuthPermission "doAsPrivileged";
permission java.security.SecurityPermission "setPolicy";
permission java.security.SecurityPermission "getPolicy";
permission java.lang.RuntimePermission "accessClassInPackage.sun.security.provider";
permission java.lang.RuntimePermission "getProtectionDomain";
};

Untuk menjalankan contoh di atas, tambahkan baris berikut saat run -Djava.security.manager -Djava.security.policy=security.policy -Djava.security.auth.login.config=jazz.config

0 comments:

 

©2009 Stay the Same | by TNB