KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jguard > jee > authentication > http > AccessFilter


1 /*
2 jGuard is a security framework based on top of jaas (java authentication and authorization security).
3 it is written for web applications, to resolve simply, access control problems.
4 version $Name$
5 http://sourceforge.net/projects/jguard/
6
7 Copyright (C) 2004 Charles GAY
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23
24 jGuard project home page:
25 http://sourceforge.net/projects/jguard/
26
27 */

28 package net.sf.jguard.jee.authentication.http;
29
30 import java.io.IOException JavaDoc;
31 import java.security.Permission JavaDoc;
32 import java.security.Permissions JavaDoc;
33 import java.security.Policy JavaDoc;
34 import java.security.PrivilegedActionException JavaDoc;
35 import java.security.PrivilegedExceptionAction JavaDoc;
36 import java.util.ArrayList JavaDoc;
37 import java.util.Collection JavaDoc;
38 import java.util.HashMap JavaDoc;
39 import java.util.HashSet JavaDoc;
40 import java.util.Iterator JavaDoc;
41 import java.util.Map JavaDoc;
42 import java.util.Set JavaDoc;
43 import java.util.regex.Matcher JavaDoc;
44 import java.util.regex.Pattern JavaDoc;
45
46 import javax.security.auth.Subject JavaDoc;
47 import javax.servlet.Filter JavaDoc;
48 import javax.servlet.FilterChain JavaDoc;
49 import javax.servlet.FilterConfig JavaDoc;
50 import javax.servlet.ServletContext JavaDoc;
51 import javax.servlet.ServletException JavaDoc;
52 import javax.servlet.ServletRequest JavaDoc;
53 import javax.servlet.ServletResponse JavaDoc;
54 import javax.servlet.http.HttpServletRequest JavaDoc;
55 import javax.servlet.http.HttpServletResponse JavaDoc;
56 import javax.servlet.http.HttpSession JavaDoc;
57
58 import net.sf.jguard.core.CoreConstants;
59 import net.sf.jguard.core.authentication.credentials.JGuardCredential;
60 import net.sf.jguard.core.authorization.permissions.URLPermission;
61 import net.sf.jguard.ext.SecurityConstants;
62 import net.sf.jguard.ext.audit.AuditManager;
63 import net.sf.jguard.ext.authentication.AuthenticationException;
64 import net.sf.jguard.ext.authentication.manager.AuthenticationManager;
65 import net.sf.jguard.ext.authentication.manager.AuthenticationManagerFactory;
66 import net.sf.jguard.ext.registration.SubjectTemplate;
67 import net.sf.jguard.ext.util.XMLUtils;
68 import net.sf.jguard.jee.authentication.callbacks.HttpCallbackHandler;
69 import net.sf.jguard.jee.authorization.http.HttpAccessControllerUtils;
70 import net.sf.jguard.jee.util.WebappUtil;
71
72 import org.apache.commons.logging.Log;
73 import org.apache.commons.logging.LogFactory;
74 import org.dom4j.Document;
75 import org.dom4j.Element;
76
77  
78
79 /**
80  * this Filter handle the control access of all request.
81  * @author <a HREF="mailto:tandilero@users.sourceforge.net">Maximiliano Batelli</a>
82  * @author <a HREF="mailto:diabolo512@users.sourceforge.net">Charles Gay</a>
83  */

84 public class AccessFilter implements Filter JavaDoc,HttpConstants{
85
86
87     private static final String JavaDoc STAR = "\\*";
88     private static final String JavaDoc DOUBLE_STAR = "\\*\\*";
89     private static Pattern JavaDoc starPattern = Pattern.compile(AccessFilter.STAR);
90
91
92     /** Logger for this class */
93     static public final Log logger = LogFactory.getLog(AccessFilter.class);
94
95     /* authentication settings */
96     //page to redirect if authentication success
97
private static String JavaDoc indexURI;
98     //page to redirect if authentication failed
99
private static URLPermission authenticationFailedURI;
100     //ressource to access to logonForm
101
private static URLPermission logonURI;
102     private static String JavaDoc logonURIStr;
103     //destination from authentication form to authenticate
104
private static URLPermission logonProcessURI;
105     //uris to logoff
106
private static Permissions JavaDoc logoffURIs;
107     //page to redirect if access to the ressource is denied
108
private static URLPermission accessDeniedURI;
109
110     //uri used to grab informations from
111
//registration form
112
private static URLPermission registerProcessURI;
113     //uri used to grab informations from
114
//registration form
115
private static String JavaDoc registerURI;
116
117     //unique name of the application
118
private static String JavaDoc applicationName;
119
120
121     //authentication schemes authorized
122
private static String JavaDoc authScheme;
123     
124     private static boolean goToLastAccessDeniedUriOnSuccess = true;
125     
126     //very important parameter which define if configuration is local to the webapp or not
127
private boolean local;
128     
129     /**
130      * Filter initialization.
131      * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
132      */

133     public void init(FilterConfig JavaDoc filterCfg) throws ServletException JavaDoc {
134         
135         logger.debug("server info = "+filterCfg.getServletContext().getServerInfo());
136         logger.debug("servletContextName="+ filterCfg.getServletContext().getServletContextName());
137         logger.debug("servlet Real Path="+ WebappUtil.getWebappHomePath(filterCfg.getServletContext(),"/"));
138         logger.debug("current Policy="+Policy.getPolicy());
139
140         ServletContext JavaDoc context = filterCfg.getServletContext();
141         applicationName = context.getServletContextName();
142         if(applicationName == null){
143             logger.fatal(" ServletContext.getServletContextName() return null \n you should fix your web.xml by adding the 'display-name' markup with the name of your webapp ");
144             throw new ServletException JavaDoc(" ServletContext.getServletContextName() return null \n you should fix your web.xml by adding the 'display-name' markup with the name of your webapp ");
145         }
146
147         String JavaDoc filterConfigurationLocation = WebappUtil.getWebappHomePath(context,filterCfg.getInitParameter(HttpConstants.CONFIGURATION_LOCATION));
148
149         Map JavaDoc filterSettings = loadFilterConfiguration(filterConfigurationLocation);
150
151         setFilterSettings(filterSettings);
152
153         context.setAttribute(CoreConstants.APPLICATION_NAME,applicationName);
154         context.setAttribute(HttpConstants.AUTH_SCHEME,authScheme);
155         context.setAttribute(HttpConstants.USERS_IN_SESSION,new ArrayList JavaDoc());
156         String JavaDoc authenticationScope = (String JavaDoc)context.getAttribute(SecurityConstants.AUTHENTICATION_SCOPE);
157         if(SecurityConstants.JVM_SCOPE.equalsIgnoreCase(authenticationScope)){
158             local = false;
159         }else{
160             local = true;
161         }
162     }
163
164     /**
165      * @param filterSettings Map which contains filter options
166      * @throws ServletException
167      */

168     private void setFilterSettings(Map JavaDoc filterSettings) throws ServletException JavaDoc {
169         indexURI = (String JavaDoc)filterSettings.get(HttpConstants.INDEX_URI);
170         authenticationFailedURI = new URLPermission("authenticationFailedURI",(String JavaDoc)filterSettings.get(HttpConstants.AUTHENTICATION_FAILED_URI));
171         logonProcessURI = new URLPermission("logonProcessURI",(String JavaDoc)filterSettings.get(HttpConstants.LOGON_PROCESS_URI));
172         logonURIStr = (String JavaDoc)filterSettings.get(HttpConstants.LOGON_URI);
173         logonURI = new URLPermission("logonURI",logonURIStr);
174         logoffURIs = new Permissions JavaDoc();
175         Iterator JavaDoc itLogoffURI = ((Set JavaDoc)filterSettings.get(HttpConstants.LOGOFF_URIS)).iterator();
176         while (itLogoffURI.hasNext()){
177             logoffURIs.add(new URLPermission("logoffURI",(String JavaDoc)itLogoffURI.next()));
178         }
179         accessDeniedURI = new URLPermission("accessDeniedURI",(String JavaDoc)filterSettings.get(HttpConstants.ACCESS_DENIED_URI));
180         registerProcessURI = new URLPermission("registerProcessURI",(String JavaDoc)filterSettings.get(HttpConstants.REGISTER_PROCESS_URI));
181         registerURI = (String JavaDoc)filterSettings.get(HttpConstants.REGISTER_URI);
182
183         //grab the authentication scheme authorized
184
authScheme = (String JavaDoc)filterSettings.get(HttpConstants.AUTH_SCHEME);
185         Collection JavaDoc authSchemes = AuthSchemesHelper.validateAuthScheme(authScheme);
186         if(authSchemes.contains(HttpConstants.FORM_AUTH)){
187             HttpCallbackHandler.setLoginField((String JavaDoc)filterSettings.get(HttpConstants.LOGIN_FIELD));
188             HttpCallbackHandler.setPasswordField((String JavaDoc)filterSettings.get(HttpConstants.PASSWORD_FIELD));
189         }
190         
191         // grab goToLastAccessDeniedUriOnSuccess value
192
String JavaDoc tmpValue = (String JavaDoc)filterSettings.get(HttpConstants.GO_TO_LAST_ACCESS_DENIED_URI_ON_SUCCESS);
193         if("false".equalsIgnoreCase(tmpValue) || "no".equalsIgnoreCase(tmpValue))
194             goToLastAccessDeniedUriOnSuccess = false;
195         
196     }
197
198
199         /**
200      * the method which handle the request.
201      * this method was inspired by the article on jaas published at <a HREF="http://www.mooreds.com/jaas.html">this</a> address.
202      * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
203      */

204     public void doFilter(ServletRequest JavaDoc request, ServletResponse JavaDoc response, FilterChain JavaDoc chain) throws IOException JavaDoc, ServletException JavaDoc {
205         HttpServletRequest JavaDoc req = (HttpServletRequest JavaDoc)request;
206         HttpServletResponse JavaDoc res = (HttpServletResponse JavaDoc)response;
207         URLPermission urlPermission = (URLPermission)buildPermission(req);
208         Subject JavaDoc subject = HttpAuthenticationUtils.getSubject(req.getSession(true));
209        
210         if(subject == null){
211             logger.debug("LAST_ACCESS_DENIED_URI="+urlPermission.getURI());
212             req.getSession(true).setAttribute(HttpConstants.LAST_ACCESS_DENIED_URI,urlPermission.getURI());
213             AuditManager.addEvent(subject," subject is null "," logonProcess phase ");
214             logonProcess(new AnonymizerRequestWrapper(req), res);
215         }else if(authenticationFailedURI.implies(urlPermission)){
216              //we always permit access to the 'authenticationFailed','logonURI', or 'accessDenied' pages.
217
StringBuffer JavaDoc sb1 = new StringBuffer JavaDoc("subject is not null and URI");
218             sb1.append(urlPermission.getURI());
219             sb1.append("= authenticationFailedURI( ").append(authenticationFailedURI.getURI()).append(")");
220             AuditManager.addEvent(subject,sb1.toString()," access authorized ");
221             chain.doFilter(request,response);
222         }else if(accessDeniedURI.implies(urlPermission)){
223             //we always permit access to the 'authenticationFailed','logonURI', or 'accessDenied' pages.
224
StringBuffer JavaDoc sb1 = new StringBuffer JavaDoc("subject is not null and URI");
225             sb1.append(urlPermission.getURI());
226             sb1.append("= accessDeniedURI( ").append(accessDeniedURI.getURI()).append(")");
227             AuditManager.addEvent(subject,sb1.toString()," access authorized ");
228             chain.doFilter(request,response);
229         }else if(logonURI.implies(urlPermission)){
230             StringBuffer JavaDoc sb2 = new StringBuffer JavaDoc("uri(").append(urlPermission.getURI()).append(")");
231             sb2.append(" is equals to logonURI(").append(logonURI.getURI()).append(") ");
232             AuditManager.addEvent(subject,sb2.toString()," logon phase ");
233             HttpCallbackHandler.buildFormChallenge(chain, req, res);
234         }else if(logonProcessURI.implies(urlPermission)){
235             StringBuffer JavaDoc sb3 = new StringBuffer JavaDoc(" uri(").append(urlPermission.getURI()).append(")").append("=logonProcessURI(").append(logonProcessURI.getURI()).append(")");
236             AuditManager.addEvent(subject,sb3.toString()," logonProcess phase ");
237             logonProcess(req, res);
238         }else if(logoffURIs.implies(urlPermission)){
239             StringBuffer JavaDoc sb4 = new StringBuffer JavaDoc("uri(").append(urlPermission.getURI()).append(")=logoffURI(").append(urlPermission.getURI()).append(")");
240             AuditManager.addEvent(subject,sb4.toString()," logoff phase ");
241             logoff(req, res, chain);
242
243         //we check that registration is defined (not defined when an SSO is present for example)
244
}else if(registerProcessURI!= null && registerURI != null && registerProcessURI.implies(urlPermission)){
245             //
246
StringBuffer JavaDoc sb5 = new StringBuffer JavaDoc("uri(").append(urlPermission.getURI()).append(")=registerProcessURI(").append(registerProcessURI.getURI()).append(")");
247             AuditManager.addEvent(subject,sb5.toString()," registerProcess phase ");
248
249             //before registration, we authenticate the user as a guest
250
//=> it "hooks" loginmodules based on credentials because the user is not yer registered
251
//but permits to execute others loginmodules like captcha one and others to avoid
252
//annoyances with robot-based mass registration
253
boolean authenticate = authenticate(new AnonymizerRequestWrapper(req), res);
254             if(authenticate== false){
255                 //we don't register the user because it fails loginModules not based on credentials
256
return;
257             }
258             boolean registerSucceed = registerProcess(req, res, chain);
259
260             if(!registerSucceed){
261                 AuditManager.addEvent(subject," registration failed " ," registerProcess phase ");
262                 if(!res.isCommitted()){
263                  res.sendRedirect(res.encodeRedirectURL(req.getContextPath()+registerURI));
264                 }else{
265                     logger.warn(" we cannot redirect to "+req.getContextPath()+registerURI+" because response is already commited ");
266                 }
267             }else if(registerSucceed){
268                 AuditManager.addEvent(subject," registration succeed " ," registerProcess phase ");
269                 //the user is registered and we submit directly its credentials to the authentication phase
270
req.getSession(true).removeAttribute(HttpConstants.AUTHN_UTILS);
271                 req.getSession(true).removeAttribute(HttpConstants.LAST_ACCESS_DENIED_URI);
272                 authenticateAfterRegistration(req, res);
273             }
274
275         }else{
276
277
278             //access denied
279
if(!HttpAccessControllerUtils.hasPermission(req,urlPermission)){
280                 //we store the last access denied URI before authentication
281
//to redirect to this ur after successful authentication
282
req.getSession(true).setAttribute(HttpConstants.LAST_ACCESS_DENIED_URI,urlPermission.getURI());
283                 StringBuffer JavaDoc sb5 = new StringBuffer JavaDoc(" subject hasn't got the permission name=").append(urlPermission.getName()).append(" actions=").append(urlPermission.getActions());
284                 AuditManager.addEvent(subject,sb5.toString()," accessdenied phase ");
285                 accessDenied(req, res);
286             }else{
287                 //access granted
288
StringBuffer JavaDoc sb6 = new StringBuffer JavaDoc(" subject has got the permission name=").append(urlPermission.getName()).append(" actions=").append(urlPermission.getActions());
289                 AuditManager.addEvent(subject,sb6.toString()," authorize phase ");
290                 authorize(chain, req, res);
291             }
292         }
293
294
295     }
296
297     /**
298      * register the user against the @link SubjectTemplate.
299      * @param req
300      * @param res
301      * @param chain
302      * @return true if registration succeed, false otherwise
303      */

304     private static boolean registerProcess(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res, FilterChain JavaDoc chain) {
305         boolean success = false;
306         AuthenticationManager auth = AuthenticationManagerFactory.getAuthenticationManager();
307         SubjectTemplate st = null;
308         try {
309             st = buildSubjectTemplate(req);
310         } catch (AuthenticationException e1) {
311             logger.error(" subject template cannot be built ",e1);
312             return false;
313         }
314         Subject JavaDoc subject = null;
315         try {
316             subject = auth.createUser(st);
317             success = true;
318         } catch (AuthenticationException e) {
319             StringBuffer JavaDoc sb7 = new StringBuffer JavaDoc(" registration failed ");
320             AuditManager.addEvent(subject,sb7.toString(), " registrationProcess phase");
321         }
322
323         return success;
324     }
325
326     /**
327      * fill in the SubjectTemplate the credentials from HttpServletRequest.
328      * @param req HttpServletRequest
329      * @return SubjectTemplate filled.
330      * @throws AuthenticationException
331      */

332     private static SubjectTemplate buildSubjectTemplate(HttpServletRequest JavaDoc req) throws AuthenticationException{
333         AuthenticationManager auth = AuthenticationManagerFactory.getAuthenticationManager();
334         SubjectTemplate defaultSt = auth.getDefaultSubjectTemplate();
335         SubjectTemplate st = new SubjectTemplate();
336         st.setName(defaultSt.getName());
337
338         //private required credentials
339
Set JavaDoc privateCredRequiredFromDefaultSt =defaultSt.getPrivateRequiredCredentials();
340         Set JavaDoc privRequiredCred = grabRegistrationForm(req, st, privateCredRequiredFromDefaultSt);
341         st.setPrivateRequiredCredentials(privRequiredCred);
342
343         //public required credentials
344
Set JavaDoc publicCredRequiredFromDefaultSt =defaultSt.getPublicRequiredCredentials();
345         Set JavaDoc pubRequiredCred = grabRegistrationForm(req, st, publicCredRequiredFromDefaultSt);
346         st.setPublicRequiredCredentials(pubRequiredCred);
347
348         //public optional credentials
349
Set JavaDoc publicCredOptionalFromDefaultSt =defaultSt.getPublicOptionalCredentials();
350         Set JavaDoc pubOptionalCred = grabRegistrationForm(req, st, publicCredOptionalFromDefaultSt);
351         st.setPublicOptionalCredentials(pubOptionalCred);
352
353         //public optional credentials
354
Set JavaDoc privateCredOptionalFromDefaultSt =defaultSt.getPrivateOptionalCredentials();
355         Set JavaDoc privOptionalCred = grabRegistrationForm(req, st, privateCredOptionalFromDefaultSt);
356         st.setPrivateOptionalCredentials(privOptionalCred);
357
358
359         return st;
360     }
361
362     /**
363      * build a set of credentials by grabbing data from HttpServletRequest.
364      * @param req HttpServletRequest
365      * @param st SubjectTemplate
366      * @param credentialsFromDefaultSt
367      * @return Set of Credential
368      */

369     private static Set JavaDoc grabRegistrationForm(HttpServletRequest JavaDoc req, SubjectTemplate st, Set JavaDoc credentialsFromDefaultSt) {
370         Iterator JavaDoc itCredentials = credentialsFromDefaultSt.iterator();
371         Set JavaDoc credSet = new HashSet JavaDoc();
372         while(itCredentials.hasNext()){
373             JGuardCredential jcredFromDefault = (JGuardCredential)itCredentials.next();
374
375             //test if we've found the credential in the http request
376
if(req.getParameter(jcredFromDefault.getId())!= null){
377                 JGuardCredential jcred = new JGuardCredential();
378                 jcred.setId(jcredFromDefault.getId());
379                 try{
380                     jcred.setValue(req.getParameter(jcredFromDefault.getId()));
381                     credSet.add(jcred);
382                 }catch(IllegalArgumentException JavaDoc iae){
383                     logger.warn(" the property "+jcredFromDefault.getId()+" doesn't exist in the HttpServletRequest ");
384                     continue;
385                 }
386             }
387
388         }
389         return credSet;
390     }
391
392
393
394     private static String JavaDoc buildRequest(HttpServletRequest JavaDoc req) {
395         String JavaDoc uriWithQuery = null;
396         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(req.getServletPath());
397         if(req.getQueryString()!=null && req.getQueryString().length()>0){
398             sb.append("?");
399             sb.append(req.getQueryString());
400         }
401         uriWithQuery = sb.toString();
402         Matcher JavaDoc matcher = starPattern.matcher(uriWithQuery);
403         uriWithQuery = matcher.replaceAll(AccessFilter.DOUBLE_STAR);
404         logger.debug("uriWithQuery="+uriWithQuery);
405         return uriWithQuery;
406     }
407
408     /**
409      *
410      * @param req
411      * @param res
412      * @throws IOException
413      */

414     private void logonProcess(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res) throws IOException JavaDoc {
415         HttpSession JavaDoc session = req.getSession(true);
416         Subject JavaDoc subject = HttpAuthenticationUtils.getSubject(session);
417         if(HttpConstants.BASIC_AUTH.equalsIgnoreCase(authScheme)){
418                String JavaDoc authorizationHeader = req.getHeader("Authorization");
419                logger.debug("authorizationHeader="+authorizationHeader);
420
421                 //first time user reach the webapp in the session => we automatically authenticate it as a GUEST
422
if(subject == null){
423                     String JavaDoc AuthorizationHeaderValue = HttpCallbackHandler.buildBasicAuthHeader(
424                                                       SecurityConstants.GUEST,SecurityConstants.GUEST,req.getCharacterEncoding());
425                     JGuardServletRequestWrapper jguardReq = new JGuardServletRequestWrapper(req);
426                     jguardReq.setHeader(HttpCallbackHandler.AUTHORIZATION,AuthorizationHeaderValue);
427                     AuditManager.addEvent(subject," BASIC authentication subject is null "," authenticate phase ");
428                     authenticate(jguardReq, res);
429                 }else if((authorizationHeader==null || !authorizationHeader.startsWith("Basic ") )){
430                     //in BASIC AUTH, we don't redirect to a login FORM page
431
//but put in the response header the challenge
432
AuditManager.addEvent(subject," subject is not null but BASIC HEADER is incorrect "+authorizationHeader," jGuard build BASIC challenge ");
433                     HttpCallbackHandler.buildBasicChallenge(res,(String JavaDoc)session.getServletContext().getAttribute(CoreConstants.APPLICATION_NAME));
434                 }else{
435                     AuditManager.addEvent(subject," BASIC AUTHENTICATION TYPE "," authenticate phase ");
436                     authenticate(req, res);
437                 }
438         }else{
439             AuditManager.addEvent(subject," AUTHENTICATION TYPE ="+authScheme," authenticate phase ");
440             authenticate(req, res);
441         }
442     }
443
444     
445     /**
446      * redirect user to either a specific uri, or send a HttpServletResponse.SC_UNAUTHORIZED
447      * @param req
448      * @param res
449      * @throws IOException
450      */

451     private void accessDenied(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res) throws IOException JavaDoc {
452         //redirect to accessDeniedURI because user is not authorized
453
//to access to this resource
454
if (logger.isDebugEnabled()) {
455             logger.debug(" access denied to "+req.getRequestURI());
456         }
457         if(accessDeniedURI== null){
458             AuditManager.addEvent(HttpAuthenticationUtils.getSubject(req.getSession(true))," access is denied to "+req.getRequestURI()+" accessDeniedURI is not defined "," jGuard send 401 http code ");
459             res.sendError(HttpServletResponse.SC_UNAUTHORIZED, " access denied ");
460         }else{
461           AuditManager.addEvent(HttpAuthenticationUtils.getSubject(req.getSession(true))," access is denied to"+req.getRequestURI()," user is redirected to accessDeniedURI"+accessDeniedURI.getURI());
462           //we encode redirect url to to be compliant with browsers which does not support cookies
463
if(!res.isCommitted()){
464           res.sendRedirect(res.encodeRedirectURL(req.getContextPath()+accessDeniedURI.getURI()));
465           }else{
466             logger.warn(" we cannot redirect to req.getContextPath()+"+accessDeniedURI.getURI()+" because response is already commited ");
467         }
468     }
469     }
470
471     /**
472      * propagate security information and continue filter chain.
473      * @param chain
474      * @param req
475      * @param res
476      * @throws IOException
477      * @throws ServletException
478      */

479     private void authorize(FilterChain JavaDoc chain, HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res) throws IOException JavaDoc, ServletException JavaDoc {
480         if (logger.isDebugEnabled()) {
481             logger.debug("doFilter() - access authorized to "+ req.getRequestURI());
482         }
483
484         // user is authorized
485
//we propagate the security informations in the Thread
486
if(System.getSecurityManager()!=null){
487                 try {
488                     propagateSecurity(new JGuardServletRequestWrapper(req),res,chain);
489                 } catch (PrivilegedActionException JavaDoc e) {
490                     logger.warn(" access denied ",e);
491                     AuditManager.addEvent(HttpAuthenticationUtils.getSubject(req.getSession(true))," a security exception "+e.getMessage()," user is redirected to accessDeniedURI("+accessDeniedURI.getURI()+")");
492                     if(!res.isCommitted()){
493                     res.sendRedirect(res.encodeRedirectURL(req.getContextPath()+accessDeniedURI.getURI()));
494                     }else{
495                         logger.warn(" we cannot redirect to "+req.getContextPath()+accessDeniedURI.getURI()+" because response is already commited ");
496                  }
497                  }
498         }else{
499             //the securityManager is not enabled, so we don't propagate
500
//security informations
501
try{
502             chain.doFilter(new JGuardServletRequestWrapper(req),res);
503             }catch(Throwable JavaDoc t){
504                 logger.fatal(t.getMessage());
505                 res.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
506             }
507         }
508     }
509
510     /**
511      * unauthenticate the user.
512      * @param request
513      * @param response
514      * @param chain
515      * @throws IOException
516      * @throws ServletException
517      */

518     private static void logoff(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, FilterChain JavaDoc chain) throws IOException JavaDoc, ServletException JavaDoc {
519         //remove Subject from session
520
HttpSession JavaDoc session = request.getSession();
521
522         HttpAuthenticationUtils auth= (HttpAuthenticationUtils)session.getAttribute(HttpConstants.AUTHN_UTILS);
523         if(auth!= null){
524             auth.logout();
525             AuditManager.addEvent(auth.getSubject()," "," user logoff ");
526         }
527
528         session.removeAttribute(HttpConstants.AUTHN_UTILS);
529
530         if (logger.isDebugEnabled()) {
531                 logger.debug("doFilter() - user logoff ");
532         }
533
534         //we invalidate the session to unbound all objects, including subject
535
try{
536            session.invalidate();
537         }catch(IllegalStateException JavaDoc ise){
538             logger.debug(" session is already invalidated ");
539         }
540
541         //authenticated user(subject!=null) is always authorize to logoff
542
chain.doFilter(request,response);
543     }
544
545     /**
546      *
547      * propagate security informations into the execution Thread.
548      * @param request
549      * @param response
550      * @param chain
551      * @throws PrivilegedActionException
552      */

553     private static void propagateSecurity(final HttpServletRequest JavaDoc request, final HttpServletResponse JavaDoc response, final FilterChain JavaDoc chain) throws PrivilegedActionException JavaDoc{
554                 HttpSession JavaDoc session = request.getSession();
555                 Subject JavaDoc subject = HttpAuthenticationUtils.getSubject(session);
556                 Subject.doAsPrivileged(subject, new PrivilegedExceptionAction JavaDoc() {
557                 public Object JavaDoc run() throws IOException JavaDoc, ServletException JavaDoc {
558                     //we wrap the ServletRequest to 'correct' the j2ee's JAAS handling
559
// according to the j2se way
560
try{
561                     chain.doFilter(new JGuardServletRequestWrapper(request),response);
562                         }catch(Throwable JavaDoc t){
563                             logger.fatal(t.getMessage());
564                             response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
565                         }
566                     // the 'null' tells the SecurityManager to consider this resource access
567
//in an isolated context, ignoring the permissions of code currently
568
//on the execution stack.
569
return null;
570                 }
571                 },null);
572
573     }
574
575
576     /**
577      * authenticate client request according the authentication Policy defined in the 'authSchemes' field.
578      * @param req
579      * @param res
580      * @return <code>true</code> if authentication succeeds, <code>false</code> otherwise
581      * @throws IOException
582      */

583     private boolean authenticate(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res) throws IOException JavaDoc {
584         boolean authenticationFailed = !HttpAuthenticationUtils.authenticate(req,res,false,local);
585         return postAuthenticationProcess(req, res, authenticationFailed);
586     }
587
588     /**
589      * authenticate client request according the authentication Policy defined in the 'authSchemes' field.
590      * @param req
591      * @param res
592      * @return <code>true</code> if authentication succeeds, <code>false</code> otherwise
593      * @throws IOException
594      */

595     private boolean authenticateAfterRegistration(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res) throws IOException JavaDoc {
596         boolean authenticationFailed = !HttpAuthenticationUtils.authenticate(req,res,true,local);
597         return postAuthenticationProcess(req, res, authenticationFailed);
598     }
599
600     private boolean postAuthenticationProcess(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res, boolean authenticationFailed) throws IOException JavaDoc {
601         
602         Subject JavaDoc subject = HttpAuthenticationUtils.getSubject(req.getSession(true));
603         
604         if(authenticationFailed){
605             if(res.isCommitted()){
606                 logger.warn(" response is already committed ");
607             }
608
609             if(HttpConstants.BASIC_AUTH.equalsIgnoreCase(authScheme)){
610                   HttpCallbackHandler.buildBasicChallenge(res,(String JavaDoc)((HttpServletRequest JavaDoc)req).getSession(true).getServletContext().getAttribute(CoreConstants.APPLICATION_NAME));
611                   return !authenticationFailed;
612              }
613             AuditManager.addEvent(subject,"authentication failed"," redirect to "+authenticationFailedURI.getURI());
614
615            if(authenticationFailedURI!=null && !authenticationFailedURI.getURI().equals("")){
616                    res.sendRedirect(res.encodeRedirectURL(req.getContextPath()+authenticationFailedURI.getURI()));
617                    AuditManager.addEvent(subject," NOT BASIC AUTHENTICATION - user is not authenticated "," redirect to "+req.getContextPath()+authenticationFailedURI.getURI());
618                
619            }else{
620                res.sendError(HttpServletResponse.SC_UNAUTHORIZED, " access denied ");
621                AuditManager.addEvent(subject," user is not authentication and authenticationFailedURI is not defined "," send"+HttpServletResponse.SC_UNAUTHORIZED+" code ");
622            }
623
624         //authentication succeed
625
}else{
626             HttpSession JavaDoc oldSession = req.getSession(true);
627             String JavaDoc redirectURI = indexURI;
628             String JavaDoc lastAccessDeniedURI = (String JavaDoc)oldSession.getAttribute(HttpConstants.LAST_ACCESS_DENIED_URI);
629             
630             //for security reasons(man-in-the-middle attack for sessionID cookie),
631
//we remove the old session if authentication is successfull
632
//and create a new session
633
//to not lost the subject, we grab in the old session HttpAuthenticationUtils
634
//and put it in the new session
635
HttpAuthenticationUtils httpAuthenticationUtils = HttpAuthenticationUtils.getHttpAuthenticationUtils(req,local);
636             subject = httpAuthenticationUtils.getSubject();
637             
638             //we test if response is committed, because
639
//when user register, it authenticate twice
640
// => the response is committed at the first step
641
if(!res.isCommitted()){
642                 //we remove this variable before invalidate the session
643
//to prevent the session listener to erase the subject
644
oldSession.removeAttribute(HttpConstants.AUTHN_UTILS);
645                 oldSession.invalidate();
646                 
647                 HttpSession JavaDoc newSession = req.getSession(true);
648                 newSession.setAttribute(HttpConstants.AUTHN_UTILS,httpAuthenticationUtils);
649             }
650             
651             //we redirect to the last 'access denied' URI before authentication
652
if(lastAccessDeniedURI!=null && lastAccessDeniedURI!="") {
653                 if(goToLastAccessDeniedUriOnSuccess)
654                     redirectURI = lastAccessDeniedURI;
655                 else {
656                     URLPermission urlPermission = new URLPermission("indexURI",indexURI);
657                     if(!HttpAccessControllerUtils.hasPermission(req,urlPermission))
658                         redirectURI = logonURIStr;
659                 }
660             }
661             if (logger.isDebugEnabled()) {
662                logger.debug(" user is authenticated and redirected to ."+redirectURI);
663             }
664             if(res.isCommitted()){
665                 logger.warn(" response is already committed ");
666             }
667
668             AuditManager.addEvent(subject," user is authenticated "," redirect to "+redirectURI);
669             if(!res.isCommitted()){
670               res.sendRedirect(res.encodeRedirectURL(req.getContextPath()+redirectURI));
671             }
672             
673         }
674         return !authenticationFailed;
675     }
676
677     /**
678      * @see javax.servlet.Filter#destroy()
679      */

680     public void destroy() {
681       //no operation to do when the webapp shutdown
682
}
683
684
685
686      /**
687      * load configuration from an XML file.
688      * @param configurationLocation
689      * @return Map containing filter configuration
690      */

691     private Map JavaDoc loadFilterConfiguration(String JavaDoc configurationLocation){
692         Document doc = XMLUtils.read(configurationLocation);
693
694         Element authentication = doc.getRootElement().element(HttpConstants.FILTER);
695         Map JavaDoc filterSettings = new HashMap JavaDoc();
696         filterSettings.put(HttpConstants.INDEX_URI,authentication.element(HttpConstants.INDEX_URI).getTextTrim());
697         filterSettings.put(HttpConstants.AUTHENTICATION_FAILED_URI,authentication.element(HttpConstants.AUTHENTICATION_FAILED_URI).getTextTrim());
698         if(authentication.element(HttpConstants.REGISTER_PROCESS_URI)!=null){
699             filterSettings.put(HttpConstants.REGISTER_PROCESS_URI,authentication.element(HttpConstants.REGISTER_PROCESS_URI).getTextTrim());
700         }
701         if(authentication.element(HttpConstants.REGISTER_URI)!=null){
702             filterSettings.put(HttpConstants.REGISTER_URI,authentication.element(HttpConstants.REGISTER_URI).getTextTrim());
703         }
704         filterSettings.put(HttpConstants.LOGON_PROCESS_URI,authentication.element(HttpConstants.LOGON_PROCESS_URI).getTextTrim());
705         filterSettings.put(HttpConstants.LOGON_URI,authentication.element(HttpConstants.LOGON_URI).getTextTrim());
706
707         Set JavaDoc logoffURIsCollection = new HashSet JavaDoc();
708         Iterator JavaDoc itLogoffURI = authentication.element(HttpConstants.LOGOFF_URIS).elements(HttpConstants.LOGOFF_URI).iterator();
709         while (itLogoffURI.hasNext()){
710             logoffURIsCollection.add(((Element)itLogoffURI.next()).getTextTrim());
711         }
712         filterSettings.put(HttpConstants.LOGOFF_URIS,logoffURIsCollection);
713
714         filterSettings.put(HttpConstants.ACCESS_DENIED_URI,authentication.element(HttpConstants.ACCESS_DENIED_URI).getTextTrim());
715         filterSettings.put(HttpConstants.AUTH_SCHEME,authentication.element(HttpConstants.AUTH_SCHEME).getTextTrim());
716         Element loginElement = authentication.element(HttpConstants.LOGIN_FIELD);
717         if (loginElement != null){
718             filterSettings.put(HttpConstants.LOGIN_FIELD,loginElement.getTextTrim());
719         }
720         Element passwordElement = authentication.element(HttpConstants.PASSWORD_FIELD);
721         if (passwordElement != null){
722             filterSettings.put(HttpConstants.PASSWORD_FIELD,passwordElement.getTextTrim());
723         }
724
725         Element goToLastAccessDeniedUriOnSuccessElement = authentication.element(HttpConstants.GO_TO_LAST_ACCESS_DENIED_URI_ON_SUCCESS);
726         if (goToLastAccessDeniedUriOnSuccessElement != null){
727             filterSettings.put(HttpConstants.GO_TO_LAST_ACCESS_DENIED_URI_ON_SUCCESS,goToLastAccessDeniedUriOnSuccessElement.getTextTrim());
728         }
729         
730         return filterSettings;
731     }
732     public Permission JavaDoc buildPermission(HttpServletRequest JavaDoc request){
733          String JavaDoc uriWithQuery = buildRequest(request);
734          logger.debug("uriWithQuery="+uriWithQuery);
735         //build the permission corresponding to the URI and prevent any '*' character to be interpreted as a regexp
736
StringBuffer JavaDoc actions = new StringBuffer JavaDoc(URLPermission.removeRegexpFromURI(uriWithQuery));
737         actions.append(',').append(request.getProtocol()).append(',').append(request.getMethod()).append("permission build from the user request");
738         URLPermission urlPermission = new URLPermission("permissionFromUser",actions.toString());
739         return urlPermission;
740     }
741 }
742
Popular Tags