Võ Văn Hải's blog

Chỉ có một điều tuyệt đối đó là mọi thứ đều tương đối…

Dùng java authentication & authorization services(jaas) cấu hình phân quyền sử dụng các bussiness methods trong ejb

A. Tạo EJB

1.       Tạo thư mục example1 để lưu tất cả vào đấy

2.       Tạo Session Beans Remote Interface:

package ejb.jaas;

import java.rmi.RemoteException;

import javax.ejb.EJBObject;

public interface Session extends EJBObject

{

public String echo(String arg) throws RemoteException;

public void noop() throws RemoteException;

}

3.       Tạo Session Beans Home Interface

package ejb.jaas;

import java.rmi.RemoteException;

import javax.ejb.CreateException;

import javax.ejb.EJBHome;

public interface SessionHome extends EJBHome

{

public Session create() throws RemoteException, CreateException;

}

4.       Tạo Stateless Session Bean

package ejb.jaas;

import java.security.Principal;

import javax.ejb.CreateException;

import javax.ejb.SessionBean;

import javax.ejb.SessionContext;

/**

@ejbHome: SessionHome

@ejbRemote: Session

*/

public class StatelessSessionBean implements SessionBean

{

private SessionContext sessionContext;

public StatelessSessionBean(){

}

public void ejbCreate() throws CreateException

{

System.out.println(“StatelessSessionBean.ejbCreate() called”);

}

public void ejbActivate()

{

System.out.println(“StatelessSessionBean.ejbActivate() called”);

}

public void ejbPassivate()

{

System.out.println(“StatelessSessionBean.ejbPassivate() called”);

}

public void ejbRemove()

{

System.out.println(“StatelessSessionBean.ejbRemove() called”);

}

public void setSessionContext(SessionContext context)

{

sessionContext = context;

}

public String echo(String arg)

{

System.out.println(“StatelessSessionBean.echo, arg=”+arg);

Principal p = sessionContext.getCallerPrincipal();

System.out.println(“StatelessSessionBean.echo, callerPrincipal=”+p);

return arg;

}

public void noop()

{

System.out.println(“StatelessSessionBean.noop”);

Principal p = sessionContext.getCallerPrincipal();

System.out.println(“StatelessSessionBean.noop, callerPrincipal=”+p);

}

}

5.       Tạo Stateful Session Bean

package ejb.jaas;

import java.security.Principal;

import javax.ejb.CreateException;

import javax.ejb.SessionBean;

import javax.ejb.SessionContext;

/**

@ejbHome: SessionHome

@ejbRemote: Session

*/

public class StatefulSessionBean implements SessionBean

{

private SessionContext sessionContext;

public void ejbCreate() throws CreateException

{

System.out.println(“StatefulSessionBean.ejbCreate() called”);

}

public void ejbActivate()

{

System.out.println(“StatefulSessionBean.ejbActivate() called”);

}

public void ejbPassivate()

{

System.out.println(“StatefulSessionBean.ejbPassivate() called”);

}

public void ejbRemove()

{

System.out.println(“StatefulSessionBean.ejbRemove() called”);

}

public void setSessionContext(SessionContext context)

{

sessionContext = context;

}

public String echo(String arg)

{

System.out.println(“StatefulSessionBean.echo, arg=”+arg);

Principal p = sessionContext.getCallerPrincipal();

System.out.println(“StatefulSessionBean.echo, callerPrincipal=”+p);

return arg;

}

public void noop()

{

System.out.println(“StatefulSessionBean.noop”);

Principal p = sessionContext.getCallerPrincipal();

System.out.println(“StatefulSessionBean.noop, callerPrincipal=”+p);

}

}

B. Cấu hình triển khai EJB

1.       Tạo ejb-jar.xml Deployment Descriptor trong thư mục META-INF

<?xml version=”1.0″ encoding=”UTF-8″?>

<!DOCTYPE ejb-jar PUBLIC “-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN”

http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd”&gt;

<ejb-jar>

<display-name>SecurityTests</display-name>

<enterprise-beans>

<session>

<description>A trival stateless session echo bean</description>

<ejb-name>StatelessSession</ejb-name>

<home>ejb.jaas.SessionHome</home>

<remote>ejb.jaas.Session</remote>

<ejb-class>ejb.jaas.StatelessSessionBean</ejb-class>

<session-type>Stateless</session-type>

<transaction-type>Container</transaction-type>

</session>

<session>

<description>A trival stateful session echo bean</description>

<ejb-name>StatefulSession</ejb-name>

<home>ejb.jaas.SessionHome</home>

<remote>ejb.jaas.Session</remote>

<ejb-class>ejb.jaas.StatefulSessionBean</ejb-class>

<session-type>Stateful</session-type>

<transaction-type>Container</transaction-type>

</session>

</enterprise-beans>

<assembly-descriptor>

<security-role>

<role-name>Echo</role-name>

</security-role>

<method-permission>

<role-name>Echo</role-name>

<method>

<ejb-name>StatelessSession</ejb-name>

<method-name>*</method-name>

</method>

<method>

<ejb-name>StatefulSession</ejb-name>

<method-name>*</method-name>

</method>

</method-permission>

<method-permission>

<role-name>Coder</role-name>

<method>

<ejb-name>StatefulSession</ejb-name>

<method-name>create</method-name>

</method>

<method>

<ejb-name>StatefulSession</ejb-name>

<method-name>remove</method-name>

</method>

<method>

<ejb-name>StatefulSession</ejb-name>

<method-name>noop</method-name>

</method>

</method-permission>

</assembly-descriptor>

</ejb-jar>

2.       Tạo jboss.xml Deployment Descriptor trong thư mục META-INF

<?xml version=”1.0″ encoding=”UTF-8″?>

<jboss>

<!– All bean containers use this security manager by default –>

<security-domain>java:/jaas/example1</security-domain>

<enterprise-beans>

<session>

<ejb-name>StatelessSession</ejb-name>

<jndi-name>example1/StatelessSession</jndi-name>

</session>

<session>

<ejb-name>StatefulSession</ejb-name>

<jndi-name>example1/StatefulSession</jndi-name>

</session>

</enterprise-beans>

</jboss>

3.       Tạo file users.properties có nội dung:

#dinh dang : <username>=<password>

scott=echoman

stark=javaman

File này khai báo với JBOSS username và password của chương trình sẽ được lookup ở đây.

4.       Tạo file roles.properties có nội dung

#dinh dang :  username=role1[,role2,…]

scott=Echo,Coder

stark=Coder

File này khai báo các roles mà user có thể sử dụng được. Như vậy, scott sẽ sử dụng được 2 roles là Echo và Coder, stark sẽ sử dụng được role Coder

Chú ý trong file ejb-jar.xml ở thẻ <assembly-descriptor>. Điều đó có nghĩa là role Echo sẽ sử dụng được tất cả các phương thức trong StatelessSessionBean cũng như StatefulSessionBean. Còn role Coder chỉ  sử dụng được 3 phương thức create, remove noop trong StatefulSessionBean

Copy 2 files này vào thư mục %JBOSS_HOME%\server\default\conf\

5.       Tạo file auth.conf có nội dung

example1 {

// properties file LoginModule ho tro cho ánh xa CallerPrincipal

org.jboss.security.auth.spi.UsersRolesLoginModule required

;

};

Copy file này vào thư mục %JBOSS_HOME%\conf\default\

6.       Tạo file compile.bat có nội dung:

javac -d . *.java

pause

Chạy file này để biên dịch các tập tin. Phải đảm bảo việc biên dịch là OK.

7.       Tạo file createJar.bat có nội dung

jar cvf JAAS_Example1.jar ejb/jaas/*.class META-INF/*.xml

pause

8.       Triển khai JAAS_Example1.jar bằng cách copy nó vào thư mục  %JBOSS_HOME%\server\default\deploy

Ta có kết quả sau trong console JBOSS

10:31:43,505 INFO  [ProxyFactory] Bound EJB Home ‘StatelessSession’ to jndi ‘example1/StatelessSession’

10:31:43,515 INFO  [ProxyFactory] Bound EJB Home ‘StatefulSession’ to jndi ‘example1/StatefulSession’

10:31:43,516 INFO  [EJBDeployer] Deployed: file:/C:/javaSoft/jboss-4.2.2.GA/server/default/deploy/JAAS_Example1.jar

9.       OK! Mọi thứ của bữa tiệc đã ngon lành. Bắt đầu thưởng thức thôi

C. Tạo client

1.       Tạo thư mục client, copy thư mục ejb đã biên dịch ỏ phần trên vào, xóa 2 class : StatefulSessionBean.class và StatelessSessionBean.class.

2.       Tạo file SessionClient.java với nội dung sau:

package client;

import java.util.Properties;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.NameCallback;

import javax.security.auth.callback.PasswordCallback;

import javax.security.auth.callback.UnsupportedCallbackException;

import javax.security.auth.login.LoginContext;

import javax.security.auth.login.LoginException;

import ejb.jaas.Session;

import ejb.jaas.SessionHome;

public class SessionClient

{

static class AppCallbackHandler implements CallbackHandler

{

private String username;

private char[] password;

public AppCallbackHandler(String username, char[] password)

{

this.username = username;

this.password = password;

}

public void handle(Callback[] callbacks) throws

java.io.IOException, UnsupportedCallbackException

{

for (int i = 0; i < callbacks.length; i++)

{

if (callbacks[i] instanceof NameCallback)

{

NameCallback nc = (NameCallback)callbacks[i];

nc.setName(username);

}

else if (callbacks[i] instanceof PasswordCallback)

{

PasswordCallback pc = (PasswordCallback)callbacks[i];

pc.setPassword(password);

}

else

{

throw new UnsupportedCallbackException(callbacks[i], “Unrecognized Callback”);

}

}

}

}

public static void main(String args[]) throws Exception

{

//chi dinh file config cho client

System.setProperty(“java.security.auth.login.config”,”client-auth.conf”);

//thiet lap tham so moi truong

Properties props = System.getProperties();

props.put( Context.INITIAL_CONTEXT_FACTORY,”org.jnp.interfaces.NamingContextFactory” );

props.put( Context.PROVIDER_URL, “localhost:1099” );

props.put( Context.URL_PKG_PREFIXES, “org.jboss.naming” );

//==============================================

String name = “scott”;//đổi sau mỗi lần chạy để thử

Char[] password =”echoman”.toCharArray();//…

String example = “example1”;

System.out.println(“+++ Running SessionClient with username=”+name+”, password=”+ new String(password+)”, example=”+example);

try

{

AppCallbackHandler handler = new AppCallbackHandler(name, password);

LoginContext lc = new LoginContext(“TestClient”, handler);

System.out.println(“Created LoginContext”);

lc.login();

System.out.println(“Login success”);

}

catch (LoginException le)

{

System.out.println(“Login failed”);

le.printStackTrace();

logger(“client.log”,le.toString());

}

try

{

System.out.println(“Looking for StatelessSession: “+example+”/StatelessSession”);

InitialContext iniContext = new InitialContext();

SessionHome home = (SessionHome) iniContext.lookup(example+”/StatelessSession”);

System.out.println(“Found StatelessSessionHome”);

Session bean = home.create();

System.out.println(“Created StatelessSession”);

System.out.println(“Bean.echo(‘Hello’) -> “+bean.echo(“Hello”));

bean.remove();

}

catch(Exception e)

{

e.printStackTrace();

logger(“client.log”,e.toString());

}

try

{

InitialContext iniContext = new InitialContext();

SessionHome home = (SessionHome) iniContext.lookup(example+”/StatefulSession”);

System.out.println(“Found StatefulSessionHome”);

Session bean = home.create();

System.out.println(“Created StatefulSession”);

bean.noop();

System.out.println(“Bean.noop() called”);

System.out.println(“Bean.echo(‘Hello’) -> “+bean.echo(“Hello”));

bean.remove();

}

catch(Exception e)

{

e.printStackTrace();

logger(“client.log”,e.toString());

}

try {

lc.logout();

System.out.println(“–>Logged-out OK.”);

} catch (Exception e) {

e.printStackTrace();

}

}

static void logger(String filename,String log ){

try{

java.io.PrintWriter out=new java.io.PrintWriter(new java.io.FileOutputStream(filename));

out.println(“Error: “+new java.util.Date().toString()+”============================”);

out.println(log);

out.println(“—-ended problem—-“);

out.close();

}catch(Exception ex){

ex.printStackTrace();

}

}

}

3.       Tạo file client-auth.conf trong thư mục client với nội dung

TestClient {

org.jboss.security.ClientLoginModule  required;

};

4.       Tạo file app.policy trong thư mục client với nội dung

grant {

permission java.security.AllPermission;

};

5.       Tạo file compile.bat với nội dung sau:

javac -d . *.java

pause

Chạy file này để biên dịch client. Phải đảm bảo mọi thứ OK.

6.       Tạo file client.bat với nội dung sau:

java -Djava.Security.policy=app.policy SessionClient

pause

7.       Đảm bảo CLASSPATH phải cần có đường dẫn đến các files (đã đề cập ở các phần trước) ở thư mục %JBOSS-HOME%\client

8.       Chạy file client để thực thi. Kết quả của 1 vài lần chạy như sau

a)    Chạy với user = scott, password = echoman, kết quả như sau

+++ Running SessionClient with username=scott, password=echoman, example=example1

Created LoginContext

Login success

Looking for StatelessSession: example1/StatelessSession

Found StatelessSessionHome

Created StatelessSession

Bean.echo(‘Hello’) -> Hello

Found StatefulSessionHome

Created StatefulSession

Bean.noop() called

Bean.echo(‘Hello’) -> Hello

–>Logged-out OK.

b)Chạy với user =scott, password =tambay, kết quả như sau

+++ Running SessionClient with username=scott, password=tambay, example=example1

Created LoginContext

Login success

Looking for StatelessSession: example1/StatelessSession

Found StatelessSessionHome

java.rmi.AccessException: SecurityException; nested exception is:

javax.security.auth.login.FailedLoginException: Password Incorrect/Password Required

–>Logged-out OK.

c)    Chạy với user=stark, password = javaman, kết quả như sau

+++ Running SessionClient with username=stark, password=javaman, example=example1

Created LoginContext

Login success

Looking for StatelessSession: example1/StatelessSession

Found StatelessSessionHome

java.rmi.AccessException: SecurityException; nested exception is:

java.lang.SecurityException: Insufficient method permissions, principal=stark, ejbName=StatelessSession, method=create, interface=HOME, requiredRoles=[Echo], principalRoles=[Coder]

–>Logged-out OK.

Xem thêm các thông báo lỗi ở file client.log.

CHÚC CÁC BẠN THÀNH CÔNG!

4 Responses to “Dùng java authentication & authorization services(jaas) cấu hình phân quyền sử dụng các bussiness methods trong ejb”

  1. Jaychen said

    chào a Hải:

    Em đã làm tất cả bước trên nhưng đến lúc thực thi phía client thì đến phần lookup thì nó tìm ko thấy, nó bị đứng ngay phần đó (hình dưới):

    Mặc dù e đã deploy thành công JAAS_Example1.jar (Hình dưới):

    Mong reply của a. Thanks 🙂

  2. Jaychen said

    e dùng JBoss 4.2.2.GA. A có thể giải thích những nguyên do vì sao nó lookup ko thấy dùm e đc ko? e search nguyên nhân nhưng vẫn chưa ra 😦

  3. Jaychen said

    E tim ra loi rui, do e luc trc e ko bit, e modify cai port de? lookup JNDI, h thi dc rui :).

    Thanks a

  4. never said

    Thanks a nhieu.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.