View Javadoc

1   /*
2   * Licensed to the Apache Software Foundation (ASF) under one or more
3   * contributor license agreements.  See the NOTICE file distributed with
4   * this work for additional information regarding copyright ownership.
5   * The ASF licenses this file to You under the Apache License, Version 2.0
6   * (the "License"); you may not use this file except in compliance with
7   * the License.  You may obtain a copy of the License at
8   *
9   *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17  package org.apache.jetspeed.security.impl;
18  
19  import java.io.IOException;
20  import java.security.Principal;
21  import java.security.PrivilegedAction;
22  
23  import javax.security.auth.Subject;
24  import javax.servlet.http.HttpSession;
25  
26  import org.apache.jetspeed.PortalReservedParameters;
27  import org.apache.jetspeed.administration.PortalAuthenticationConfiguration;
28  import org.apache.jetspeed.pipeline.PipelineException;
29  import org.apache.jetspeed.pipeline.valve.AbstractValve;
30  import org.apache.jetspeed.pipeline.valve.SecurityValve;
31  import org.apache.jetspeed.pipeline.valve.ValveContext;
32  import org.apache.jetspeed.request.RequestContext;
33  import org.apache.jetspeed.security.JSSubject;
34  
35  /***
36   * <p>
37   * AbstractSecurityValve
38   * </p>
39   * <p>
40   *
41   * </p>
42   * @author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
43   * @version $Id: AbstractSecurityValve.java 544402 2007-06-05 06:20:00Z taylor $
44   *
45   */
46  public abstract class AbstractSecurityValve extends AbstractValve implements SecurityValve
47  {
48      protected PortalAuthenticationConfiguration authenticationConfiguration = null;
49      
50      /***
51       * 
52       * <p>
53       * getSubject
54       * </p>
55       *  Should build and return a <code>javax.security.Subject</code>
56       * @param request
57       * @return Subject
58       */
59      protected abstract Subject getSubject(RequestContext request) throws Exception;
60      
61      /***
62       * 
63       * <p>
64       * getUserPrincipal
65       * </p>
66       * Should build and return a <code>java.security.Principal</code> that represents the user name
67       * the Subject returned from <code>getSubject()</code> 
68       * @param request
69       * @return Principal
70       * @throws Exception
71       */
72      protected abstract Principal getUserPrincipal(RequestContext request) throws Exception;
73          
74      /***
75       * 
76       * <p>
77       * getSubjectFromSession
78       * </p>
79       * 
80       * @param request
81       * @return javax.security.Subject or <code>null</code> if there is no servlet session attribute defined
82       * for the key <code>org.apache.jetspeed.PortalReservedParameters.SESSION_KEY_SUBJECT</code>.
83       */
84      protected final Subject getSubjectFromSession(RequestContext request) throws Exception
85      {
86          return (Subject) request.getRequest().getSession().getAttribute(PortalReservedParameters.SESSION_KEY_SUBJECT);
87      }
88  
89      /***
90       * <p>
91       * invoke
92       * </p>
93       * 
94       * <p>
95       * Uses <code>getSubject()</code> to call <code>ValveContext.invokeNext()</code> via 
96       * <code>JSSubjectdoAsPrivileged()</code>.  This method also takes care of setting the value of
97       * the <code>RequestContext.subject</code> property and the session attribute 
98       * <code>org.apache.jetspeed.PortalReservedParameters.SESSION_KEY_SUBJECT</code>
99       * </p>
100      *
101      * @see org.apache.jetspeed.pipeline.valve.Valve#invoke(org.apache.jetspeed.request.RequestContext, org.apache.jetspeed.pipeline.valve.ValveContext)
102      * @param request
103      * @param context
104      * @throws PipelineException if the is an error encountered during any security operations.
105      */
106     public void invoke( RequestContext request, ValveContext context ) throws PipelineException
107     {
108         if (isSessionExpired(request))
109         {
110             return; // short circuit processing and redirect
111         }
112     
113         // initialize/validate security subject
114         Subject subject;
115         try
116         {
117             subject = getSubject(request);
118         }
119         catch (Exception e1)
120         {
121            throw new PipelineException(e1.getMessage(), e1);
122         }
123         request.getRequest().getSession().setAttribute(PortalReservedParameters.SESSION_KEY_SUBJECT, subject);            
124         
125         // set request context subject
126         request.setSubject(subject);
127         
128         // Pass control to the next Valve in the Pipeline and execute under
129         // the current subject
130         final ValveContext vc = context;
131         final RequestContext rc = request;            
132         PipelineException pe = (PipelineException) JSSubject.doAsPrivileged(subject, new PrivilegedAction()
133         {
134             public Object run() 
135             {
136                  try
137                 {
138                     vc.invokeNext(rc);                 
139                     return null;
140                 }
141                 catch (PipelineException e)
142                 {
143                     return e;
144                 }                    
145             }
146         }, null);
147         
148         if(pe != null)
149         {
150             throw pe;
151         }           
152     }
153     
154     /***
155      * Check for hard limit session expiration time out
156      * 
157      * @param request
158      * @return
159      * @throws PipelineException
160      */
161     protected boolean isSessionExpired(RequestContext request) throws PipelineException    
162     {
163         if (authenticationConfiguration != null && authenticationConfiguration.isMaxSessionHardLimitEnabled())
164         {
165             HttpSession session = request.getRequest().getSession();
166             long sessionCreationTime = session.getCreationTime();
167             long currentTime = System.currentTimeMillis();
168             if ((currentTime - sessionCreationTime) > authenticationConfiguration.getMsMaxSessionHardLimit())
169             {
170                 session.invalidate();
171                 String redirector = request.getRequest().getContextPath() + authenticationConfiguration.getTimeoutRedirectLocation();
172                 // System.out.println("logging user out " + redirector + ", " + (currentTime - sessionCreationTime) + ", " + this.msMaxSessionHardLimit);
173                 try
174                 {
175                     request.getResponse().sendRedirect(redirector);
176                 }
177                 catch (IOException e)
178                 {
179                     throw new PipelineException(e);
180                 }
181                 return true;
182             }
183             else
184             {
185                 // System.out.println("Not logging user out: " + (currentTime - sessionCreationTime) + ", " + this.msMaxSessionHardLimit);
186             }
187         }
188         return false;        
189     }
190     
191 }