星期四, 九月 11, 2008

JAASRealm和Jboss(CMA) Container Manager Authentication

这是为了结合JAAS和CMA两者的有点提出的接口。
在http://www.jboss.org/file-access/default/members/jbossweb/freezone/docs/2.1.0/realm-howto.html#JAASRealm,描述了相关配置
web.xml

<Realm className="org.jboss.web.tomcat.security.JBossSecurityMgrRealm"
certificatePrincipal="org.jboss.security.auth.certs.SubjectDNMapping"
allRolesMode="authOnly"
debug="99"
/>


其他配置同JAAS标准配置一样,需要在web.xml,login-config.xml和LoginModule中调用同一个appName

但是注意,在这个LoginModule你必须自己保存用户的验证信息。
It is the responsibility of your login module to create and save User and Role objects representing Principals for the user

下列代码就是Jboss实现的:org.jboss.web.tomcat.security.login.WebAuthentication


/*
* JBoss, Home of Professional Open Source
* Copyright 2007, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.web.tomcat.security.login;

import java.security.Principal;
import java.security.cert.X509Certificate;

import javax.naming.NamingException;

import org.apache.catalina.Session;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.connector.Request;
import org.jboss.web.tomcat.security.SecurityAssociationValve;

//$Id$

/**
* JBAS-4077: Programmatic Web Login
* @author Anil.Saldhana@redhat.com
* @since Mar 12, 2007
* @version $Revision$
*/
public class WebAuthentication
{
private static final String AUTH_TYPE = "PROGRAMMATIC_WEB_LOGIN";
public WebAuthentication()
{
}

/**
* Login an user via the CLIENT-CERT method
* @param certs X509 certificates
* @return Authenticated User Principal
*/
public boolean login(X509Certificate[] certs)
{
//Get the active request
Request request = (Request) SecurityAssociationValve.activeRequest.get();
if(request == null)
throw new IllegalStateException("request is null");
Principal p = request.getContext().getRealm().authenticate(certs);
if(p != null)
{
register(request,p, null, null);
}
return p!= null;
}

/**
* Login an user via the BASIC, FORM, DIGEST methods
* @param username
* @param credential
* @return
* @throws NamingException
*/
public boolean login(String username, Object credential)
{
//Get the active request
Request request = (Request) SecurityAssociationValve.activeRequest.get();
if(request == null)
throw new IllegalStateException("request is null");

Principal p = null;
if(credential instanceof String)
{
p = request.getContext().getRealm().authenticate(username, (String)credential);
}
else if (credential instanceof byte[])
{
p = request.getContext().getRealm().authenticate(username, (byte[])credential);
}
if(p != null)
{
register(request,p, username, credential);
}
return p != null;
}

/**
* Log the user out
*
*/
public void logout()
{
//Get the active request
Request request = (Request) SecurityAssociationValve.activeRequest.get();
if(request == null)
throw new IllegalStateException("request is null");
unregister(request);
}

/**
* Register the principal with the request, session etc just the way AuthenticatorBase does
* @param request Catalina Request
* @param principal User Principal generated via authentication
* @param username username passed by the user (null for client-cert)
* @param credential Password (null for client-cert and digest)
*/
protected void register(Request request, Principal principal, String username, Object password)
{
request.setAuthType(AUTH_TYPE);
request.setUserPrincipal(principal);

//Cache the authentication principal in the session
Session session = request.getSessionInternal(false);
if(session != null)
{
session.setAuthType(AUTH_TYPE);
session.setPrincipal(principal);
if (username != null)
session.setNote(Constants.SESS_USERNAME_NOTE, username);
else
session.removeNote(Constants.SESS_USERNAME_NOTE);
if (password != null)
session.setNote(Constants.SESS_PASSWORD_NOTE, getPasswordAsString(password));
else
session.removeNote(Constants.SESS_PASSWORD_NOTE);
}
}

/**
* Log the user out
* @param request
*/
protected void unregister(Request request)
{
request.setAuthType(null);
request.setUserPrincipal(null);

//Cache the authentication principal in the session
Session session = request.getSessionInternal(false);
if(session != null)
{
session.setAuthType(null);
session.setPrincipal(null);
session.removeNote(Constants.SESS_USERNAME_NOTE);
session.removeNote(Constants.SESS_PASSWORD_NOTE);
}
}

private String getPasswordAsString(Object cred)
{
String p = null;

if(cred instanceof String)
{
p = (String)cred;
}
else if(cred instanceof byte[])
{
p = new String((byte[])cred);
}
return p;
}
}