View Javadoc

1   /*
2    * $Id: HttpBasicAuthenticationFilter.java 20297 2010-11-22 18:49:18Z aperepel $
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.module.acegi.filters.http;
12  
13  import org.mule.api.MuleEvent;
14  import org.mule.api.MuleMessage;
15  import org.mule.api.config.MuleProperties;
16  import org.mule.api.lifecycle.InitialisationException;
17  import org.mule.api.security.Authentication;
18  import org.mule.api.security.SecurityContext;
19  import org.mule.api.security.SecurityException;
20  import org.mule.api.security.SecurityProviderNotFoundException;
21  import org.mule.api.security.UnauthorisedException;
22  import org.mule.api.security.UnknownAuthenticationTypeException;
23  import org.mule.api.security.UnsupportedAuthenticationSchemeException;
24  import org.mule.config.i18n.CoreMessages;
25  import org.mule.module.acegi.AcegiAuthenticationAdapter;
26  import org.mule.module.acegi.i18n.AcegiMessages;
27  import org.mule.security.AbstractEndpointSecurityFilter;
28  import org.mule.transport.http.HttpConnector;
29  import org.mule.transport.http.HttpConstants;
30  
31  import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
32  import org.apache.commons.codec.binary.Base64;
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
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(AcegiMessages.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             UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
130                 username, password);
131             authRequest.setDetails(event.getMessage().getInboundProperty(MuleProperties.MULE_ENDPOINT_PROPERTY));
132 
133             Authentication authResult;
134 
135             Authentication authentication = new AcegiAuthenticationAdapter(authRequest);
136 
137             try
138             {
139                 authResult = getSecurityManager().authenticate(authentication);
140             }
141             catch (UnauthorisedException e)
142             {
143                 // Authentication failed
144                 if (logger.isDebugEnabled())
145                 {
146                     logger.debug("Authentication request for user: " + username + " failed: " + e.toString());
147                 }
148                 setUnauthenticated(event);
149                 throw new UnauthorisedException(CoreMessages.authFailedForUser(username), e);
150             }
151 
152             // Authentication success
153             if (logger.isDebugEnabled())
154             {
155                 logger.debug("Authentication success: " + authResult.toString());
156             }
157 
158             SecurityContext context = getSecurityManager().createSecurityContext(authResult);
159             context.setAuthentication(authResult);
160             event.getSession().setSecurityContext(context);
161         }
162         else if (header == null)
163         {
164             setUnauthenticated(event);
165             throw new UnauthorisedException(event, event.getSession().getSecurityContext(),
166                 getEndpoint(), this);
167         }
168         else
169         {
170             setUnauthenticated(event);
171             throw new UnsupportedAuthenticationSchemeException(
172                 AcegiMessages.basicFilterCannotHandleHeader(header),event);
173         }
174     }
175 
176     protected void setUnauthenticated(MuleEvent event)
177     {
178         String realmHeader = "Basic realm=";
179         if (realm != null)
180         {
181             realmHeader += "\"" + realm + "\"";
182         }
183         MuleMessage msg = event.getMessage();
184         msg.setOutboundProperty(HttpConstants.HEADER_WWW_AUTHENTICATE, realmHeader);
185         msg.setOutboundProperty(HttpConnector.HTTP_STATUS_PROPERTY, HttpConstants.SC_UNAUTHORIZED);
186     }
187 
188     /**
189      * Authenticates the current message if authenticate is set to true. This method
190      * will always populate the secure context in the session
191      * 
192      * @param event the current event being dispatched
193      * @throws org.mule.api.security.SecurityException if authentication fails
194      */
195     @Override
196     public void authenticateOutbound(MuleEvent event)
197         throws SecurityException, SecurityProviderNotFoundException
198     {
199         if (event.getSession().getSecurityContext() == null)
200         {
201             if (isAuthenticate())
202             {
203                 throw new UnauthorisedException(event, event.getSession().getSecurityContext(),
204                     event.getEndpoint(), this);
205             }
206             else
207             {
208                 return;
209             }
210         }
211 
212         Authentication auth = event.getSession().getSecurityContext().getAuthentication();
213         if (isAuthenticate())
214         {
215             auth = getSecurityManager().authenticate(auth);
216             if (logger.isDebugEnabled())
217             {
218                 logger.debug("Authentication success: " + auth.toString());
219             }
220         }
221 
222         StringBuffer header = new StringBuffer(128);
223         header.append("Basic ");
224         String token = auth.getCredentials().toString();
225         header.append(new String(Base64.encodeBase64(token.getBytes())));
226 
227         event.getMessage().setOutboundProperty(HttpConstants.HEADER_AUTHORIZATION, header.toString());
228     }
229 
230 }