View Javadoc

1   /*
2    * $Id: HttpBasicAuthenticationFilter.java 22370 2011-07-11 08:31:38Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.transport.http.filters;
12  
13  import org.mule.api.MuleEvent;
14  import org.mule.api.MuleMessage;
15  import org.mule.api.lifecycle.InitialisationException;
16  import org.mule.api.security.Authentication;
17  import org.mule.api.security.SecurityContext;
18  import org.mule.api.security.SecurityException;
19  import org.mule.api.security.SecurityProviderNotFoundException;
20  import org.mule.api.security.UnauthorisedException;
21  import org.mule.api.security.UnknownAuthenticationTypeException;
22  import org.mule.api.security.UnsupportedAuthenticationSchemeException;
23  import org.mule.config.i18n.CoreMessages;
24  import org.mule.security.AbstractEndpointSecurityFilter;
25  import org.mule.security.DefaultMuleAuthentication;
26  import org.mule.security.MuleCredentials;
27  import org.mule.transport.http.HttpConnector;
28  import org.mule.transport.http.HttpConstants;
29  import org.mule.transport.http.i18n.HttpMessages;
30  
31  import org.apache.commons.codec.binary.Base64;
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  
35  
36  /**
37   * <code>HttpBasicAuthenticationFilter</code> TODO
38   */
39  public class HttpBasicAuthenticationFilter extends AbstractEndpointSecurityFilter
40  {
41      /**
42       * logger used by this class
43       */
44      protected static final Log logger = LogFactory.getLog(HttpBasicAuthenticationFilter.class);
45  
46      private String realm;
47  
48      private boolean realmRequired = true;
49  
50      public HttpBasicAuthenticationFilter()
51      {
52          super();
53      }
54  
55      public HttpBasicAuthenticationFilter(String realm)
56      {
57          this.realm = realm;
58      }
59  
60      @Override
61      protected void doInitialise() throws InitialisationException
62      {
63          if (realm == null)
64          {
65              if (isRealmRequired())
66              {
67                  throw new InitialisationException(HttpMessages.authRealmMustBeSetOnFilter(), this);
68              }
69              else
70              {
71                  logger.warn("There is no security realm set, using default: null");
72              }
73          }
74      }
75  
76      public String getRealm()
77      {
78          return realm;
79      }
80  
81      public void setRealm(String realm)
82      {
83          this.realm = realm;
84      }
85  
86      public boolean isRealmRequired()
87      {
88          return realmRequired;
89      }
90  
91      public void setRealmRequired(boolean realmRequired)
92      {
93          this.realmRequired = realmRequired;
94      }
95  
96      /**
97       * Authenticates the current message if authenticate is set to true. This method
98       * will always populate the secure context in the session
99       *
100      * @param event the current message recieved
101      * @throws org.mule.api.security.SecurityException if authentication fails
102      */
103     @Override
104     public void authenticateInbound(MuleEvent event)
105         throws SecurityException, SecurityProviderNotFoundException, UnknownAuthenticationTypeException
106     {
107         String header = event.getMessage().getInboundProperty(HttpConstants.HEADER_AUTHORIZATION);
108 
109         if (logger.isDebugEnabled())
110         {
111             logger.debug("Authorization header: " + header);
112         }
113 
114         if ((header != null) && header.startsWith("Basic "))
115         {
116             String base64Token = header.substring(6);
117             String token = new String(Base64.decodeBase64(base64Token.getBytes()));
118 
119             String username = "";
120             String password = "";
121             int delim = token.indexOf(":");
122 
123             if (delim != -1)
124             {
125                 username = token.substring(0, delim);
126                 password = token.substring(delim + 1);
127             }
128 
129             Authentication authResult;
130             Authentication authentication = createAuthentication(username, password, event);
131 
132             try
133             {
134                 authResult = getSecurityManager().authenticate(authentication);
135             }
136             catch (UnauthorisedException e)
137             {
138                 // Authentication failed
139                 if (logger.isDebugEnabled())
140                 {
141                     logger.debug("Authentication request for user: " + username + " failed: " + e.toString());
142                 }
143                 setUnauthenticated(event);
144                 throw new UnauthorisedException(CoreMessages.authFailedForUser(username), e);
145             }
146 
147             // Authentication success
148             if (logger.isDebugEnabled())
149             {
150                 logger.debug("Authentication success: " + authResult.toString());
151             }
152 
153             SecurityContext context = getSecurityManager().createSecurityContext(authResult);
154             context.setAuthentication(authResult);
155             event.getSession().setSecurityContext(context);
156         }
157         else if (header == null)
158         {
159             setUnauthenticated(event);
160             throw new UnauthorisedException(event, event.getSession().getSecurityContext(), this);
161         }
162         else
163         {
164             setUnauthenticated(event);
165             throw new UnsupportedAuthenticationSchemeException(
166                 HttpMessages.basicFilterCannotHandleHeader(header), event);
167         }
168     }
169 
170     protected Authentication createAuthentication(String username, String password, MuleEvent event)
171     {
172         return new DefaultMuleAuthentication(new MuleCredentials(username, password.toCharArray()), event);
173     }
174 
175     protected void setUnauthenticated(MuleEvent event)
176     {
177         String realmHeader = "Basic realm=";
178         if (realm != null)
179         {
180             realmHeader += "\"" + realm + "\"";
181         }
182         MuleMessage msg = event.getMessage();
183         msg.setOutboundProperty(HttpConstants.HEADER_WWW_AUTHENTICATE, realmHeader);
184         msg.setOutboundProperty(HttpConnector.HTTP_STATUS_PROPERTY, HttpConstants.SC_UNAUTHORIZED);
185     }
186 
187     /**
188      * Authenticates the current message if authenticate is set to true. This method
189      * will always populate the secure context in the session
190      *
191      * @param event the current event being dispatched
192      * @throws org.mule.api.security.SecurityException if authentication fails
193      */
194     @Override
195     public void authenticateOutbound(MuleEvent event)
196         throws SecurityException, SecurityProviderNotFoundException
197     {
198         SecurityContext securityContext = event.getSession().getSecurityContext();
199         if (securityContext == null)
200         {
201             if (isAuthenticate())
202             {
203                 throw new UnauthorisedException(event, securityContext, this);
204             }
205             else
206             {
207                 return;
208             }
209         }
210 
211         Authentication auth = securityContext.getAuthentication();
212         if (isAuthenticate())
213         {
214             auth = getSecurityManager().authenticate(auth);
215             if (logger.isDebugEnabled())
216             {
217                 logger.debug("Authentication success: " + auth.toString());
218             }
219         }
220 
221         StringBuffer header = new StringBuffer(128);
222         header.append("Basic ");
223         String token = auth.getCredentials().toString();
224         header.append(new String(Base64.encodeBase64(token.getBytes())));
225 
226         event.getMessage().setOutboundProperty(HttpConstants.HEADER_AUTHORIZATION, header.toString());
227     }
228 }