วันพุธที่ 5 พฤษภาคม พ.ศ. 2553

Bonita and Ldap Configuration (Module Login)

Share it Please
เนื่องจาก bonita นั้นไม่มี module login ที่ใช้ ldap ในการ authentication ดังนั้นเราต้อง implement ส่วนนี้ขึ้นมาเอง โดยขั้นตอนที่เราต้องทำคือสร้าง class ที่ implement interface AuthenticationService

public interface AuthenticationService {
    /**
     * Check whether a user has admin privileges or not
     * @param username the user's username
     * @return true if the user has admin privileges, false
  otherwise
     * @throws UserNotFoundException
     */
    boolean isUserAdmin(String username) throws UserNotFoundException;
    /**
     * Check some user's credentials
     * @param username the user's username
     * @param password the user's password
     * @return true if the credentials are valid, false otherwise
     */
    boolean checkUserCredentials(String username, String password);
}  

ตัวอย่าง class ที่ implement เรียบร้อยแล้ว

public class LdapZimbraLoginModule implements AuthenticationService {

    private String connection;
    private String ldapDN;

    public LdapZimbraLoginModule(String connection, String ldapDN) {
        super();
        this.connection = connection;
        this.ldapDN = ldapDN;
    }

    public boolean isUserAdmin(String username) throws UserNotFoundException {
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "ldap://domain:port");
        env.put(Context.SECURITY_PRINCIPAL, username);
        env.put(Context.SECURITY_CREDENTIALS, password);
        try {
            DirContext ctx = new InitialDirContext(env);
            SearchControls sc = new SearchControls();
            sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
            NamingEnumeration results = ctx.search("ou=people,dc=example,dc=com", "(zimbraIsAdminAccount=TRUE)", sc);
            while (results.hasMore()) {
                SearchResult searchResult = (SearchResult) results.next();
                Attributes attributes = searchResult.getAttributes();
                Attribute attr = attributes.get("uid");
                if (username.trim().equals(attr.get().toString().trim())){
                    return true;
                }
            }
            ctx.close();
        } catch (javax.naming.NamingException r) {
        }
        return false;
    }

    public boolean checkUserCredentials(String username, String password) {
            Hashtable env = new Hashtable();
            env.put(Context.INITIAL_CONTEXT_FACTORY, 
      "com.sun.jndi.ldap.LdapCtxFactory");
            env.put(Context.PROVIDER_URL, this.connection);
            env.put(Context.SECURITY_PRINCIPAL, 
      "uid=" + 
      username.split("@")[0] + 
      ",ou=people," + 
      this.ldapDN);
            env.put(Context.SECURITY_CREDENTIALS, password);
            DirContext ctx;
            try {
                ctx = new InitialDirContext(env);
                ctx.close();
                return true;
            } catch (javax.naming.NamingException r) {
            }
            return false;
    }
}

และควรจะนำไปไว้ที่ bonita-runtime-5.1/bonita-server/src/main/java/org/ow2/bonita/services/impl/ เพื่อ ความเป็นระเบียบ จากนั้นให้ build code ในส่วนของ bonita-server จะได้ไฟล์ bonita-server-5.x.jar

ให้นำ jar ไฟล์ที่ได้ไป deploy ที่ server ของเรา (ทับของเก่าเลยนะครับ)

TOMCAT_ROOT/lib/
** TOMCAT_ROOT คือ tomcat ที่ได้มาจากการ build ตัว console ของ bonita

จากนั้นไปแก้ไข authentication service ให้ไปเรียก class ที่เราสร้างขึ้นที่ไฟล์

TOMCAT_ROOT/conf/bonita-environment.xml

โดยแก้ไขจาก

<authentication-service class="org.ow2.bonita.services.impl.DbAuthentication" name="authentication-service">
  <arg>

    <string value="bonita-session:core"></string>
  </arg>
</authentication-service>


ให้เป็น

<authentication-service name='authentication-service' class='org.ow2.bonita.services.impl.LdapZimbraLoginModule'>
           <arg><string value='ldap://domain:port' /></arg>
           <arg><string value='dc=example,dc=com' /></arg>
</authentication-service>


โดยค่า <arg> คือ parameter ที่ส่งไปยัง class LdapZimbraLoginModule

สรุปหลักการโดยคร่าวๆ คือให้สร้าง class ที่ implement AuthenticationService interface เพื่อเป็นตัว check ว่าจะ login ผ่านเมื่อใด จากนั้นแก้ไขให้ server ไปเรียกใช้ class นั้นครับ

วิธีข้างต้นเป็นวิธีที่ ดิบ+เถื่อนนะครับ เกิดจากการแกะ code แล้วแก้เอาดื้อๆ ซึ่งจริงๆแล้ว มีวิธีที่ดีกว่านี้อยู่ครับ ตามนี้เลย http://www.bonitasoft.org/forum/viewtopic.php?id=2397
ซึ่งผมอ่านแล้วไม่ค่อยเข้าใจเท่าไร

-------------------------------------------------------

thanks for @iporsut

Blogroll

About