001 /*
002 Licensed to the Apache Software Foundation (ASF) under one
003 or more contributor license agreements. See the NOTICE file
004 distributed with this work for additional information
005 regarding copyright ownership. The ASF licenses this file
006 to you under the Apache License, Version 2.0 (the
007 "License"); you may not use this file except in compliance
008 with the License. You may obtain a copy of the License at
009
010 http://www.apache.org/licenses/LICENSE-2.0
011
012 Unless required by applicable law or agreed to in writing,
013 software distributed under the License is distributed on an
014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 KIND, either express or implied. See the License for the
016 specific language governing permissions and limitations
017 under the License.
018 */
019 package org.apache.wiki.auth.login;
020
021 import java.io.IOException;
022 import java.security.Principal;
023
024 import javax.security.auth.callback.Callback;
025 import javax.security.auth.callback.UnsupportedCallbackException;
026 import javax.security.auth.login.FailedLoginException;
027 import javax.security.auth.login.LoginException;
028 import javax.servlet.http.HttpServletRequest;
029 import javax.servlet.http.HttpSession;
030
031 import org.apache.log4j.Logger;
032
033 import org.apache.wiki.auth.WikiPrincipal;
034
035 /**
036 * <p>
037 * Logs in a user by extracting authentication data from an Http servlet
038 * session. First, the module tries to extract a Principal object out of the
039 * request directly using the servlet requests's <code>getUserPrincipal()</code>
040 * method. If one is found, authentication succeeds. If there is no
041 * Principal in the request, try calling <code>getRemoteUser()</code>. If
042 * the <code>remoteUser</code> exists but the UserDatabase can't find a matching
043 * profile, a generic WikiPrincipal is created with this value. If neither
044 * <code>userPrincipal</code> nor <code>remoteUser</code> exist in the request, the login fails.
045 * </p>
046 * <p>
047 * This module must be used with a CallbackHandler that supports the following
048 * Callback types:
049 * </p>
050 * <ol>
051 * <li>{@link HttpRequestCallback} - supplies the Http request object, from
052 * which the getRemoteUser and getUserPrincipal are extracted</li>
053 * <li>{@link UserDatabaseCallback} - supplies the user database for looking up
054 * the value of getRemoteUser</li>
055 * </ol>
056 * <p>
057 * After authentication, the Subject will contain the Principal that
058 * represents the logged-in user.</p>
059 *
060 * @since 2.3
061 */
062 public class WebContainerLoginModule extends AbstractLoginModule
063 {
064
065 protected static final Logger log = Logger.getLogger( WebContainerLoginModule.class );
066
067 /**
068 * Logs in the user.
069 * @see javax.security.auth.spi.LoginModule#login()
070 *
071 * @return {@inheritDoc}
072 * @throws {@inheritDoc}
073 */
074 public boolean login() throws LoginException
075 {
076 HttpRequestCallback rcb = new HttpRequestCallback();
077 Callback[] callbacks = new Callback[] { rcb };
078 String userId = null;
079
080 try
081 {
082 // First, try to extract a Principal object out of the request
083 // directly. If we find one, we're done.
084 m_handler.handle( callbacks );
085 HttpServletRequest request = rcb.getRequest();
086 if ( request == null )
087 {
088 throw new LoginException( "No Http request supplied." );
089 }
090 HttpSession session = request.getSession(false);
091 String sid = (session == null) ? NULL : session.getId();
092 Principal principal = request.getUserPrincipal();
093 if ( principal == null )
094 {
095 // If no Principal in request, try the remoteUser
096 if ( log.isDebugEnabled() )
097 {
098 log.debug( "No userPrincipal found for session ID=" + sid);
099 }
100 userId = request.getRemoteUser();
101 if ( userId == null )
102 {
103 if ( log.isDebugEnabled() )
104 {
105 log.debug( "No remoteUser found for session ID=" + sid);
106 }
107 throw new FailedLoginException( "No remote user found" );
108 }
109 principal = new WikiPrincipal( userId, WikiPrincipal.LOGIN_NAME );
110 }
111 if ( log.isDebugEnabled() )
112 {
113 log.debug("Logged in container principal " + principal.getName() + "." );
114 }
115 m_principals.add( principal );
116
117 return true;
118 }
119 catch( IOException e )
120 {
121 log.error( "IOException: " + e.getMessage() );
122 return false;
123 }
124 catch( UnsupportedCallbackException e )
125 {
126 log.error( "UnsupportedCallbackException: " + e.getMessage() );
127 return false;
128 }
129 }
130 }