|  | @@ -12,6 +12,7 @@
 | 
	
		
			
				|  |  |   * See the License for the specific language governing permissions and
 | 
	
		
			
				|  |  |   * limitations under the License.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  package net.sf.acegisecurity.ui.basicauth;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import net.sf.acegisecurity.Authentication;
 | 
	
	
		
			
				|  | @@ -45,13 +46,13 @@ import javax.servlet.http.HttpServletResponse;
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * Processes a HTTP request's BASIC authorization headers, putting the result
 | 
	
		
			
				|  |  |   * into the <code>SecurityContextHolder</code>.
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | + * 
 | 
	
		
			
				|  |  |   * <p>
 | 
	
		
			
				|  |  |   * For a detailed background on what this filter is designed to process, refer
 | 
	
		
			
				|  |  |   * to <A HREF="http://www.faqs.org/rfcs/rfc1945.html">RFC 1945, Section
 | 
	
		
			
				|  |  |   * 11.1</A>. Any realm name presented in the HTTP request is ignored.
 | 
	
		
			
				|  |  |   * </p>
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | + * 
 | 
	
		
			
				|  |  |   * <p>
 | 
	
		
			
				|  |  |   * In summary, this filter is responsible for processing any request that has a
 | 
	
		
			
				|  |  |   * HTTP request header of <code>Authorization</code> with an authentication
 | 
	
	
		
			
				|  | @@ -60,28 +61,28 @@ import javax.servlet.http.HttpServletResponse;
 | 
	
		
			
				|  |  |   * "Aladdin" with password "open sesame" the following header would be
 | 
	
		
			
				|  |  |   * presented:
 | 
	
		
			
				|  |  |   * </p>
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | + * 
 | 
	
		
			
				|  |  |   * <p>
 | 
	
		
			
				|  |  |   * <code>Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==</code>.
 | 
	
		
			
				|  |  |   * </p>
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | + * 
 | 
	
		
			
				|  |  |   * <p>
 | 
	
		
			
				|  |  |   * This filter can be used to provide BASIC authentication services to both
 | 
	
		
			
				|  |  |   * remoting protocol clients (such as Hessian and SOAP) as well as standard
 | 
	
		
			
				|  |  |   * user agents (such as Internet Explorer and Netscape).
 | 
	
		
			
				|  |  |   * </p>
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | + * 
 | 
	
		
			
				|  |  |   * <P>
 | 
	
		
			
				|  |  |   * If authentication is successful, the resulting {@link Authentication} object
 | 
	
		
			
				|  |  |   * will be placed into the <code>SecurityContextHolder</code>.
 | 
	
		
			
				|  |  |   * </p>
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | + * 
 | 
	
		
			
				|  |  |   * <p>
 | 
	
		
			
				|  |  |   * If authentication fails, an {@link AuthenticationEntryPoint} implementation
 | 
	
		
			
				|  |  |   * is called. Usually this should be {@link BasicProcessingFilterEntryPoint},
 | 
	
		
			
				|  |  |   * which will prompt the user to authenticate again via BASIC authentication.
 | 
	
		
			
				|  |  |   * </p>
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | + * 
 | 
	
		
			
				|  |  |   * <p>
 | 
	
		
			
				|  |  |   * Basic authentication is an attractive protocol because it is simple and
 | 
	
		
			
				|  |  |   * widely deployed. However, it still transmits a password in clear text and
 | 
	
	
		
			
				|  | @@ -90,7 +91,7 @@ import javax.servlet.http.HttpServletResponse;
 | 
	
		
			
				|  |  |   * authentication wherever possible. See {@link
 | 
	
		
			
				|  |  |   * net.sf.acegisecurity.ui.digestauth.DigestProcessingFilter}.
 | 
	
		
			
				|  |  |   * </p>
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | + * 
 | 
	
		
			
				|  |  |   * <p>
 | 
	
		
			
				|  |  |   * <b>Do not use this class directly.</b> Instead configure
 | 
	
		
			
				|  |  |   * <code>web.xml</code> to use the {@link
 | 
	
	
		
			
				|  | @@ -101,10 +102,17 @@ import javax.servlet.http.HttpServletResponse;
 | 
	
		
			
				|  |  |   * @version $Id$
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  public class BasicProcessingFilter implements Filter, InitializingBean {
 | 
	
		
			
				|  |  | +    //~ Static fields/initializers =============================================
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      private static final Log logger = LogFactory.getLog(BasicProcessingFilter.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //~ Instance fields ========================================================
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      private AuthenticationEntryPoint authenticationEntryPoint;
 | 
	
		
			
				|  |  |      private AuthenticationManager authenticationManager;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    //~ Methods ================================================================
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      public void setAuthenticationEntryPoint(
 | 
	
		
			
				|  |  |          AuthenticationEntryPoint authenticationEntryPoint) {
 | 
	
		
			
				|  |  |          this.authenticationEntryPoint = authenticationEntryPoint;
 | 
	
	
		
			
				|  | @@ -130,8 +138,7 @@ public class BasicProcessingFilter implements Filter, InitializingBean {
 | 
	
		
			
				|  |  |              "An AuthenticationEntryPoint is required");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    public void destroy() {
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    public void destroy() {}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public void doFilter(ServletRequest request, ServletResponse response,
 | 
	
		
			
				|  |  |          FilterChain chain) throws IOException, ServletException {
 | 
	
	
		
			
				|  | @@ -165,40 +172,47 @@ public class BasicProcessingFilter implements Filter, InitializingBean {
 | 
	
		
			
				|  |  |                  password = token.substring(delim + 1);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,
 | 
	
		
			
				|  |  | -                    password);
 | 
	
		
			
				|  |  | -            authRequest.setDetails(new WebAuthenticationDetails(httpRequest,
 | 
	
		
			
				|  |  | -                    false));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            Authentication authResult;
 | 
	
		
			
				|  |  | +            // Only reauthenticate if username doesn't match ContextHolder and user isn't authenticated (see SEC-53)
 | 
	
		
			
				|  |  | +            Authentication existingAuth = SecurityContextHolder.getContext()
 | 
	
		
			
				|  |  | +                                                               .getAuthentication();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if ((existingAuth == null)
 | 
	
		
			
				|  |  | +                || !existingAuth.getName().equals(username)
 | 
	
		
			
				|  |  | +                || !existingAuth.isAuthenticated()) {
 | 
	
		
			
				|  |  | +                UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,
 | 
	
		
			
				|  |  | +                        password);
 | 
	
		
			
				|  |  | +                authRequest.setDetails(new WebAuthenticationDetails(
 | 
	
		
			
				|  |  | +                        httpRequest, false));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                Authentication authResult;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                try {
 | 
	
		
			
				|  |  | +                    authResult = authenticationManager.authenticate(authRequest);
 | 
	
		
			
				|  |  | +                } catch (AuthenticationException failed) {
 | 
	
		
			
				|  |  | +                    // Authentication failed
 | 
	
		
			
				|  |  | +                    if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | +                        logger.debug("Authentication request for user: "
 | 
	
		
			
				|  |  | +                            + username + " failed: " + failed.toString());
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    SecurityContextHolder.getContext().setAuthentication(null);
 | 
	
		
			
				|  |  | +                    authenticationEntryPoint.commence(request, response, failed);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    return;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            try {
 | 
	
		
			
				|  |  | -                authResult = authenticationManager.authenticate(authRequest);
 | 
	
		
			
				|  |  | -            } catch (AuthenticationException failed) {
 | 
	
		
			
				|  |  | -                // Authentication failed
 | 
	
		
			
				|  |  | +                // Authentication success
 | 
	
		
			
				|  |  |                  if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | -                    logger.debug("Authentication request for user: " +
 | 
	
		
			
				|  |  | -                        username + " failed: " + failed.toString());
 | 
	
		
			
				|  |  | +                    logger.debug("Authentication success: "
 | 
	
		
			
				|  |  | +                        + authResult.toString());
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                SecurityContextHolder.getContext().setAuthentication(null);
 | 
	
		
			
				|  |  | -                authenticationEntryPoint.commence(request, response, failed);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            // Authentication success
 | 
	
		
			
				|  |  | -            if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | -                logger.debug("Authentication success: " +
 | 
	
		
			
				|  |  | -                    authResult.toString());
 | 
	
		
			
				|  |  | +                SecurityContextHolder.getContext().setAuthentication(authResult);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            SecurityContextHolder.getContext().setAuthentication(authResult);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          chain.doFilter(request, response);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    public void init(FilterConfig arg0) throws ServletException {
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    public void init(FilterConfig arg0) throws ServletException {}
 | 
	
		
			
				|  |  |  }
 |