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 }