星期四, 二月 26, 2004

Jboss /JAAS/OpenLDAP 完全配置手册.

你现在看的是http://sunose.blogspot.com
测试环境windowsxp 中文版本sp1 及Redhat 7.1 Jboss 3.2.2 with Tomcat bundle 4.1.27

1.配置Jboss login-config.xml加入以下内容:
<application-policy name="AdminRealm"> 这个将要用在web Moduler里
<authentication>
<login-module code="org.jboss.security.auth.spi.LdapLoginModule" flag="required">
<module-option name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</module-option>
<module-option name="java.naming.provider.url">ldap://localhost:389/</module-option>
<module-option name="java.naming.security.authentication">simple</module-option>
<module-option name="principalDNPrefix">cn=</module-option>
<module-option name="principalDNSuffix">,dc=sunose,dc=com</module-option>
<module-option name="rolesCtxDN">o=roles,dc=sunose,dc=com</module-option>
<module-option name="roleAttributeID">description</module-option>
<!--module-option name="userRolesCtxDNAttributeName">o=roles,dc=sunose,dc=com</module-option-->
<module-option name="uidAttributeID">sn</module-option>
<module-option name="matchOnUserDN">false</module-option>
<module-option name="unauthenticatedIdentity">nobody</module-option>
</login-module>
</authentication>
</application-policy>
2.开发CallbackHander类.或直接使用Jboss自带的:SecurityAssociationHandler
org.jboss.security.auth.callback.SecurityAssociationHandler放在jboss_home\all\lib\jbosssx.jar 文件中.

package org.sunose;

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 java.io.IOException;

public class LoginCallbackHandler implements CallbackHandler {
public LoginCallbackHandler()
{
this.username = null;
this.password = null;
}

/**
* The username to be provided when prompted.
*/
private String username;
/**
* The password to be provided when prompted.
*/
private String password;
public LoginCallbackHandler(String pusername, String ppassword)
{

setUsername(pusername);
setPassword(ppassword);
}
public void setUsername(String username)
{
if (username == null)
{
this.username = "";
return;
}
this.username = username;
}
public void setPassword(String password)
{
if (password == null)
{
this.password = "";
return;
}
this.password = password;
}
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException
{
// Loop over all Callbacks
for (int i = 0; i < callbacks.length; i++)
{
Callback cb = callbacks[i];
if (cb instanceof NameCallback)
{
System.out.println("set username"+username);
((NameCallback)cb).setName(username);
}
else if (cb instanceof PasswordCallback)
{
// JAAS specifies that the password is a char[]
System.out.println("set password"+password);
((PasswordCallback)cb).setPassword(password.toCharArray());
}
else
{
throw new UnsupportedCallbackException(
cb, "Unrecognized Callback");
}
}
}




}
3.配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>jaascallback</display-name>

<servlet>
<servlet-name>loginservice</servlet-name>
<servlet-class>org.sunose.LoginService</servlet-class>
<security-role-ref>
<role-name>AdminRealm</role-name>
<role-link>AdminRealm</role-link>
</security-role-ref>
</servlet>
<servlet-mapping>
<servlet-name>loginservice</servlet-name>
<url-pattern>/loginservice</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>EntireApplication</web-resource-name>
<url-pattern>/*.jsp</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>AdminRealm</role-name>
</auth-constraint>
<user-data-constraint>
<description>no description</description>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>AdminRealm</realm-name>
<form-login-config>
<form-login-page>/index.jsp</form-login-page>
<form-error-page>/error.html</form-error-page>
</form-login-config>
</login-config>

<security-role>
<role-name>AdminRealm</role-name>
</security-role>

</web-app>

4.配置jboss-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.3V2//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd">
<jboss-web>
<security-domain>AdminRealm</security-domain>
<context-root>jaascallback</context-root>
</jboss-web>
5.开发servlet.
package org.sunose;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
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 java.io.IOException;
import javax.security.auth.login.*;
import javax.security.auth.*;
import org.jboss.security.auth.callback.*;
import org.jboss.security.SimplePrincipal;
import java.security.*;

public class LoginService extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=GBK";

//Initialize global variables
public void init() throws ServletException {
}

//Process the HTTP Get request
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
HttpServletRequest re=request;
String cusr=(String)re.getParameter("username");
String cpass=(String)re.getParameter("password");
if(cusr==null)cusr=" ";
if(cpass == null)cpass=" ";
LoginContext lc=null;
Enumeration ttt=re.getHeaderNames();
while(ttt.hasMoreElements())
{
String temp=(String)ttt.nextElement();
System.out.println(temp+"="+re.getHeader(temp));
}
System.out.println(cusr+"/"+cpass);

try
{
lc = new LoginContext("AdminRealm",new SecurityAssociationHandler(new SimplePrincipal(cusr),cpass));
//关键之重:LoginContext(String name...)必须同在Jboss login-config.xml定义的<application-policy name=...>相同.

lc.login();

}catch(Exception e)
{
System.out.println(e.getMessage());
response.getWriter().write(e.getMessage());
response.getWriter().write(":(");
return;
}
Subject gets = lc.getSubject();
Set p= gets.getPrincipals();
Iterator pi=p.iterator();
while( pi.hasNext())
{
System.out.println("Principle="+pi.next());
}
Principal t1=request.getUserPrincipal();
if(t1 !=null)System.out.println("UserPrincipal="+t1.getName());
System.out.println(request.isUserInRole("AdminRealm"));
System.out.println(request.isUserInRole("Admin"));
System.out.println(request.isUserInRole("manager"));
System.out.println(request.isUserInRole("members:AdminRealm"));
System.out.println("-------------start---------");
System.out.println(request.getAuthType());
System.out.println(request.getUserPrincipal());
System.out.println(request.getRemoteUser());
System.out.println("-------------over---------");

response.sendRedirect("check/frame.jsp");
}

//Process the HTTP Post request
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

//Clean up resources
public void destroy() {
}
}

6.开发login.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>
index
</title>
</head>
<body bgcolor="#ffffff">
<h1>
JBuilder Generated JSP
</h1>
<form method="post" action="loginservice">
<br><br>
username:<input type="text " name="username" >
password:<input type="password" name="password" maxlentgh=12>
<input type="submit" name="Submit" value="Submit">
<input type="reset" value="Reset">
</form>
</body>
</html>

7.配置OpenLdap:
根据login-config.xml中的有关配置,填写有关entiry属性。
建立test.ldif
# Organization for Test Corporation 组织
dn: dc=test,dc=com
objectClass: dcObject
objectClass: organization
dc: test
o: Test Corporation
description: The Test Corporation

# Organizational Role for Directory Manager in group 角色
dn: cn=mana312gers817,dc=test,dc=com
objectClass: organizationalRole
cn: mana312gers817
description: Directory Manager of mana312gers817 group

使用:slapadd -l test.ldif 输入LDAP数据库(Ldap Server必须先启动)

8.发步。测试.