Dain,
Thanks for your clear instructions and the custom security interceptor that
you provided. By following your example I know have my Tomcat security
sucessfully drawing off the user.properties and roles.properties I have
configured jBoss with and can logon either at the JSP layer or via a client
that goes straight to the beans seemlessly.
Long live open source ;-) (I continue my new crusade to get this message
across to my bosses and our customers).
Thanks also to the other responders on the mailing list (there aren't many
lists with this level of traffic I'd want to keep receiving but I guess I'll
stick around a while on this one),
Pete
--
Pete Bennett (mailto:[EMAIL PROTECTED])
Principal Architect, Synomics Ltd.
http://www.synomics.com
-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED]]On Behalf Of Ivan Bolcina
Sent: 03 May 2001 09:17
To: '[EMAIL PROTECTED]'
Subject: RE: [JBoss-user] Tomcat JBoss security integration How-to
Hello.
I have trouble integrating jboss and tomcat.
I have setup jaas on jboss, written client which uses jaas to get initial
context and it works ok.
How do I connect from JSP pages. Why can't I use "Context ctx=new
InitialContext()"?
If you have working setup of "conf" directory on "jboss" and "conf" stuff in
tomcat, can you PLEASE post them here(maybe also application.xml and
ejb-jar.xml....).I thing it would be useful to a lot of people.
bye and thanx,
ivan bolcina
-----Original Message-----
From: Dain Sundstrom [mailto:[EMAIL PROTECTED]]
Sent: Thursday, May 03, 2001 5:57 AM
To: '[EMAIL PROTECTED]'
Subject: [JBoss-user] Tomcat JBoss security integration How-to
Recently, I have seen several posts asking how to integrate Tomcat and JBoss
security. The current JBossRealm requires you to add users to both the
tomcat and JBoss security systems or configure the tomcat JDBCRealm and
JBoss DatabaseServerLoginModule to point to the same database table. This
is all a big pain, so I wrote a new Tomcat interceptor which performs
authentication and authorization via the JBoss JAAS code. The steps
required to setup this interceptor follow.
1. Create the jar
a. Copy the code (later in message) onto your machine. You can
change the package if you like.
b. Compile (requires servlet.jar webserver.jar jaas.jar
jboss-jaas.jar jbosssx.jar)
c. Jar it
d. Copy it to jboss/lib/ext
Here is the ant target I use.
<target name="realm" depends="compile">
<delete file="${dist.home}/hypothermic-tomcat.jar" />
<jar jarfile="${dist.home}/hypothermic-tomcat.jar">
<fileset dir="${classes.home}"
includes="com/hypothermic/security/*.class" />
</jar>
<copy file="${dist.home}/hypothermic-tomcat.jar"
todir="${jboss.lib}/ext" />
</target>
2. Secure your EJBs.
a. ejb-jar.xml Mark your EJBs as protected.
<assembly-descriptor>
<method-permission>
<role-name>user</role-name>
<method>
<ejb-name>YourBean</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
</assembly-descriptor>
b. jboss.xml Set the authentication and authorization manager.
<container-configurations>
<container-configuration>
<container-name>Standard CMP
EntityBean</container-name>
<role-mapping-manager>java:/jaas/other</role-mapping-manager>
<authentication-module>java:/jaas/other</authentication-module>
</container-configuration>
</container-configurations>
<enterprise-beans>
<entity>
<ejb-name>YourBean</ejb-name
<container-name>Standard CMP
EntityBean</container-name>
</entity>
</enterprise-beans>
3. Secure your WAR (web.xml)
<security-constraint>
<web-resource-collection>
<web-resource-name>util</web-resource-name>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login.jsp</form-error-page>
</form-login-config>
</login-config>
4. Setup Tomcat
a. add interceptor to server.xml immediately before the
LoadOnStartupInterceptor
<RequestInterceptor
className="com.hypothermic.security.HypothermicRealm" />
b. Comment out all other security interceptors (SimpleRealm
JbossRealm JDBCRealm).
5. Add your users to JBoss
I hope I didn't leave out any steps. If you find any bugs or have any
enhancements, please email me.
-Dain Sundstrom
package com.hypothermic.security;
import org.apache.tomcat.core.Request;
import org.apache.tomcat.core.Response;
import org.apache.tomcat.core.Context;
import org.apache.tomcat.util.SecurityTools;
import org.apache.tomcat.core.BaseInterceptor;
import org.jboss.security.SecurityAssociation;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.auth.UsernamePasswordHandler;
import javax.servlet.http.HttpSession;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.security.Principal;
import java.security.acl.Group;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;
import java.util.Hashtable;
/**
* Integrates Tomcat and Jboss security by redirecting Tomcat authentication
and
* authorization calls to the JBoss JAAS code.
* @author Dain Sundstrom
*/
public class HypothermicRealm extends BaseInterceptor {
private String subjectKey = "j_subject";
private String loginContextName = "other";
/**
* The key that is used to store the Subject in the session
attributes.
* @param subjectKey the key
*/
public void setSubjectKey(String subjectKey) {
this.subjectKey = subjectKey;
}
/**
* The name used by JAAS during Login for determining spi
* @param loginContextName the name
*/
public void setLoginContextName(String loginContextName) {
this.loginContextName = loginContextName;
}
/**
* Authenticates user uning the JBoss JAAS code.
* @param request the request
* @param response the response
*/
public int authenticate(Request request, Response response){
HttpSession session = request.getSession(true);
session.removeAttribute(subjectKey);
// get the username and password
Hashtable credentials = getCredentials(request);
String username = (String)credentials.get("username");
String password = (String)credentials.get("password");
if(username != null && password != null) {
try {
// attempt to login via JAAS
CallbackHandler handler = new
UsernamePasswordHandler(username, password.toCharArray());
LoginContext loginContext = new
LoginContext(loginContextName, handler);
loginContext.login();
Subject subject = loginContext.getSubject();
if(subject != null) {
// we are logged in
session.setAttribute(subjectKey,
subject);
// set the remote user
request.setRemoteUser(username);
// set the auth method to way every
was expected in the context...
Context ctx = request.getContext();
if (ctx != null) {
request.setAuthType(ctx.getAuthMethod());
}
// Set the security association in
JBoss
SecurityAssociation.setPrincipal(
new SimplePrincipal( username ) );
SecurityAssociation.setCredential(
password.toCharArray() );
}
} catch(LoginException e) {
// Login Failed
e.printStackTrace();
}
}
return 0;
}
/**
* Determines if the user is a member of the requested roles. This
authorization if
* checked with the JBoss JAAS code.
* @param request the request
* @param response the response
* @param roles the roles of which the user must belong.
*/
public int authorize( Request request, Response response, String
roles[] ) {
// if no roles are needed we are done
if(roles==null || roles.length==0) {
return 0;
}
// if we are not authenticated, there is nothing to do.
String user = request.getRemoteUser();
if(user==null) {
return 401;
}
// Get the Subject that was set during authentication.
HttpSession session = request.getSession(true);
Subject subject = (Subject)session.getAttribute(subjectKey);
if(subject == null) {
return 401;
}
// Get the roles to which this subject belongs.
String userRoles[] = getRoles(subject);
// Set the roles in the request.
request.setUserRoles(userRoles);
// Does this user belong to the proper roles?
if(SecurityTools.haveRole(userRoles, roles)) {
return 0;
}
// too bad not authorized
return 401;
}
/**
* Attempt to retrieve the user's credentials from the usual Tomcat
* locations, and if that fails, attempt to get them directly from
the request.
* @param request the request
*/
protected Hashtable getCredentials(Request request) {
Hashtable credentials = new Hashtable();
// first try to get the crentials from the standard tomcat
location
SecurityTools.credentials(request, credentials);
String username = (String)credentials.get("username");
String password = (String)credentials.get("password");
// ok tomcat doesn't have the credentials
if(username == null || password == null) {
// try to get the username and password out of the
request
username = request.getParameter("j_username");
password = request.getParameter("j_password");
if(username != null && password != null) {
// got them stuff them into the session
attributes
//(where tomcat looks)
HttpSession session =
request.getSession(true);
session.setAttribute( "j_username",
username);
session.setAttribute( "j_password",
password);
}
}
return credentials;
}
/**
* Get the names of every role of which the subject is a member.
* @param subject the subect
*/
protected String[] getRoles(Subject subject) {
Set groups = subject.getPrincipals(Group.class);
Iterator iterator = groups.iterator();
while(iterator.hasNext()) {
Group group = (Group) iterator.next();
if("Roles".equals(group.getName())) {
return getRoles(group);
}
}
return null;
}
/**
* Get the names of every group of which the group is a member.
* @param group the group
*/
protected String[] getRoles(Group group) {
Set roleSet = new HashSet();
getRoles(group, roleSet);
// convert Set to String[];
String[] roles = new String[roleSet.size()];
roles = (String[])roleSet.toArray(roles);
return roles;
}
/**
* Adds the names of every group of which the group is a member to
the set.
* @param group the group
* @param roleSet the set of group names
*/
protected void getRoles(Group group, Set roleSet) {
Enumeration enum = group.members();
while(enum.hasMoreElements()) {
Principal principal = (Principal)enum.nextElement();
if(principal instanceof Group) {
getRoles((Group)principal, roleSet);
} else {
roleSet.add(principal.getName());
}
}
}
}
_______________________________________________
JBoss-user mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-user
_______________________________________________
JBoss-user mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-user
_______________________________________________
JBoss-user mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-user