001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.web.tomcat.security;
023:
024: import java.io.IOException;
025: import java.security.Principal;
026: import java.util.StringTokenizer;
027:
028: import javax.management.JMException;
029: import javax.management.ObjectName;
030: import javax.servlet.http.Cookie;
031:
032: import org.apache.catalina.Realm;
033: import org.apache.catalina.Session;
034: import org.apache.catalina.authenticator.Constants;
035: import org.apache.catalina.connector.Request;
036: import org.apache.catalina.connector.Response;
037: import org.apache.catalina.deploy.LoginConfig;
038: import org.jboss.logging.Logger;
039:
040: /**
041: * JBAS-2283: Provide custom header based authentication support
042: *
043: * Header Authenticator that deals with userid from the request header
044: * Requires two attributes configured on the Tomcat Service - one for
045: * the http header denoting the authenticated identity and the other
046: * is the SESSION cookie
047: *
048: * @author <a href="mailto:Anil.Saldhana@jboss.org">Anil Saldhana</a>
049: * @version $Revision$
050: * @since Sep 11, 2006
051: */
052: public class GenericHeaderAuthenticator extends
053: ExtendedFormAuthenticator {
054: protected static Logger log = Logger
055: .getLogger(GenericHeaderAuthenticator.class);
056: protected boolean trace = log.isTraceEnabled();
057:
058: public GenericHeaderAuthenticator() {
059: super ();
060: }
061:
062: public boolean authenticate(Request request, Response response,
063: LoginConfig config) throws IOException {
064: log.trace("Authenticating user");
065:
066: Principal principal = request.getUserPrincipal();
067: if (principal != null) {
068: if (trace)
069: log.trace("Already authenticated '"
070: + principal.getName() + "'");
071: return true;
072: }
073:
074: Realm realm = context.getRealm();
075: Session session = request.getSessionInternal(true);
076:
077: String username = getUserId(request);
078: String password = getSessionCookie(request);
079:
080: //Check if there is sso id as well as sessionkey
081: if (username == null || password == null) {
082: log
083: .trace("Username is null or password(sessionkey) is null:fallback to form auth");
084: return super .authenticate(request, response, config);
085: }
086: principal = realm.authenticate(username, password);
087:
088: if (principal == null) {
089: forwardToErrorPage(request, response, config);
090: return false;
091: }
092:
093: session.setNote(Constants.SESS_USERNAME_NOTE, username);
094: session.setNote(Constants.SESS_PASSWORD_NOTE, password);
095: request.setUserPrincipal(principal);
096:
097: register(request, response, principal, Constants.FORM_METHOD,
098: username, password);
099: return true;
100: }
101:
102: /**
103: * Get the username from the request header
104: * @param request
105: * @return
106: */
107: protected String getUserId(Request request) {
108: String ssoid = null;
109: //We can have a comma-separated ids
110: String ids = "";
111: try {
112: ids = this .getIdentityHeaderId();
113: } catch (JMException e) {
114: if (trace)
115: log.trace("getUserId exception", e);
116: }
117: if (ids == null || ids.length() == 0)
118: throw new IllegalStateException(
119: "Http headers configuration in tomcat service missing");
120:
121: StringTokenizer st = new StringTokenizer(ids, ",");
122: while (st.hasMoreTokens()) {
123: ssoid = request.getHeader(st.nextToken());
124: if (ssoid != null)
125: break;
126: }
127: if (trace)
128: log.trace("SSOID-" + ssoid);
129: return ssoid;
130: }
131:
132: /**
133: * Obtain the session cookie from the request
134: * @param request
135: * @return
136: */
137: protected String getSessionCookie(Request request) {
138: Cookie[] cookies = request.getCookies();
139: log.trace("Cookies:" + cookies);
140: int numCookies = cookies != null ? cookies.length : 0;
141:
142: //We can have comma-separated ids
143: String ids = "";
144: try {
145: ids = this .getSessionCookieId();
146: log.trace("Session Cookie Ids=" + ids);
147: } catch (JMException e) {
148: if (trace)
149: log.trace("checkSessionCookie exception", e);
150: }
151: if (ids == null || ids.length() == 0)
152: throw new IllegalStateException(
153: "Session cookies configuration in tomcat service missing");
154:
155: StringTokenizer st = new StringTokenizer(ids, ",");
156: while (st.hasMoreTokens()) {
157: String cookieToken = st.nextToken();
158: String val = getCookieValue(cookies, numCookies,
159: cookieToken);
160: if (val != null)
161: return val;
162: }
163: if (trace)
164: log.trace("Session Cookie not found");
165: return null;
166: }
167:
168: /**
169: * Get the configured header identity id
170: * in the tomcat service
171: * @return
172: * @throws JMException
173: */
174: protected String getIdentityHeaderId() throws JMException {
175: return (String) mserver.getAttribute(new ObjectName(
176: "jboss.web:service=WebServer"), "HttpHeaderForSSOAuth");
177: }
178:
179: /**
180: * Get the configured session cookie id in the tomcat service
181: * @return
182: * @throws JMException
183: */
184: protected String getSessionCookieId() throws JMException {
185: return (String) mserver.getAttribute(new ObjectName(
186: "jboss.web:service=WebServer"),
187: "SessionCookieForSSOAuth");
188: }
189:
190: /**
191: * Get the value of a cookie if the name matches the token
192: * @param cookies array of cookies
193: * @param numCookies number of cookies in the array
194: * @param token Key
195: * @return value of cookie
196: */
197: protected String getCookieValue(Cookie[] cookies, int numCookies,
198: String token) {
199: for (int i = 0; i < numCookies; i++) {
200: Cookie cookie = cookies[i];
201: log.trace("Matching cookieToken:" + token
202: + " with cookie name=" + cookie.getName());
203: if (token.equals(cookie.getName())) {
204: if (trace)
205: log.trace("Cookie-" + token + " value="
206: + cookie.getValue());
207: return cookie.getValue();
208: }
209: }
210: return null;
211: }
212: }
|