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  
18  /*Created on: Dec 5, 2005 */
19  
20  package org.apache.jetspeed.portlet.sso;
21  
22  import java.io.IOException;
23  import java.security.AccessControlContext;
24  import java.security.AccessController;
25  import javax.portlet.ActionRequest;
26  import javax.portlet.ActionResponse;
27  import javax.portlet.PortletConfig;
28  import javax.portlet.PortletContext;
29  import javax.portlet.PortletException;
30  import javax.portlet.PortletURL;
31  import javax.portlet.RenderRequest;
32  import javax.portlet.RenderResponse;
33  import javax.security.auth.Subject;
34  
35  import org.apache.jetspeed.security.JSSubject;
36  import org.apache.jetspeed.sso.SSOException;
37  import org.apache.jetspeed.sso.SSOProvider;
38  import org.apache.portals.bridges.common.ScriptPostProcess;
39  import org.apache.portals.bridges.velocity.GenericVelocityPortlet;
40  
41  /***
42   * SSOProxyPortlet
43   * This portlet can be used as a bridge to any URL.
44   * It acts as a http client and therefore it can store
45   * cookies.
46   * The main purpose is that the SSOProxy portlet authenticates
47   * any SSO credential for the principal user not knowing in advance
48   * what URL the user might select. No login prompt will appear for any url
49   * in the portlet for that an SSO entry exists and the principal user has permissions.
50   * 
51   * @author Roger Ruttimann <rogerrut@apache.org>
52   *
53   */
54  public class SSOProxyPortlet extends GenericVelocityPortlet {
55      private PortletContext context;
56      private SSOProvider sso;
57      
58      /* Re-use Proxy client inside the SSO Component */
59      private boolean isAuthenticated = false;
60      
61      /*** Default encoding UTF-8*/
62      public String defaultEncoding = "UTF-8";
63      
64      /*** Block Size */
65      static final int BLOCK_SIZE = 4096;
66      
67      /*** ACTION_PARAMETER_SSOPROXY*/
68      static final String ACTION_PARAMETER_SSOPROXY = "SSOProxy";
69      
70      /*** Preference values */
71      /*** DestinationURL */
72      static final String DESTINATION_URL = "DestinationURL";
73      
74      /*** SSOSite */
75      static final String SSO_SITE = "SSOSite";
76      
77      /*** ForceSSORefresh*/
78      static final String FORCE_SSO_REFRESH = "ForceSSORefresh";
79      
80      /*** Encoding*/
81      static final String ENCODING = "Encoding";
82      
83      private String destinationURL;
84      private String ssoSite;
85      private String encoding;
86  
87      public void init(PortletConfig config) throws PortletException
88      {
89          super.init(config);
90          context = getPortletContext();
91          sso = (SSOProvider)context.getAttribute("cps:SSO");
92          if (null == sso)
93          {
94             throw new PortletException("Failed to find SSO Provider on portlet initialization");
95          }
96          
97      }
98      
99      public void processAction(ActionRequest request, ActionResponse actionResponse)
100     throws PortletException, IOException
101     {
102        	String ssoProxyAction = request.getParameter(ACTION_PARAMETER_SSOPROXY); 
103 //       	System.out.println("SSOProxy Action value [" + ssoProxyAction + "]");
104        	
105      	if ( ssoProxyAction != null && ssoProxyAction.length() > 0)
106      		this.destinationURL = ssoProxyAction;
107      	else
108      		this.destinationURL = request.getParameter(DESTINATION_URL);
109      	
110      	
111         this.ssoSite = request.getParameter(SSO_SITE);
112         this.encoding = request.getParameter(ENCODING);
113         if (this.encoding == null)
114         	this.encoding =  this.defaultEncoding;
115 
116         // save the prefs
117         super.processAction(request, actionResponse);
118     }
119     
120     public void doView(RenderRequest request, RenderResponse response)
121     throws PortletException, IOException
122     {
123         String forceRefresh = request.getPreferences().getValue(FORCE_SSO_REFRESH, "false");
124 
125         if (destinationURL == null || destinationURL.length() == 0)
126         {
127             // No destination configured Switch to configure View
128              request.setAttribute(PARAM_VIEW_PAGE, this.getPortletConfig().getInitParameter(PARAM_EDIT_PAGE));
129             setupPreferencesEdit(request, response);
130             super.doView(request, response);
131             return;
132         }
133         
134 //      Set the content type
135         response.setContentType("text/html");
136         
137         /*
138          * Call into the SSO Proxy and process the result page
139          */
140         boolean doRefresh = false;
141         if ( (forceRefresh.compareToIgnoreCase("TRUE") == 0) || this.isAuthenticated == false)
142         	doRefresh = true;
143        
144         try
145         {
146         	StringBuffer page= new StringBuffer();
147             Subject subject = getSubject(); 
148             if (ssoSite == null || ssoSite.length() ==0)
149             	page.append(sso.useSSO(subject, destinationURL,doRefresh));
150             else
151             	page.append(sso.useSSO(subject, destinationURL,ssoSite, doRefresh));
152             
153             // Authentication done at least once
154             this.isAuthenticated = true;
155             /*
156             bis.mark(BLOCK_SIZE);
157             String pageEncoding = getContentCharSet(bis);
158             if (pageEncoding == null)
159             {
160             	pageEncoding = encoding;
161             }
162             
163             Reader read = new InputStreamReader(bis, encoding);
164             
165             
166 			char[] bytes = new char[BLOCK_SIZE];
167 			
168 			int len = read.read(bytes, 0, BLOCK_SIZE);			
169 			while (len > 0)
170 			{
171 				page.append(bytes, 0, len);
172 				len = read.read(bytes, 0, BLOCK_SIZE);
173 			}
174 			
175             //Done
176             read.close();
177             */
178             // Rewrite
179 			// Post Process for generated page		
180 			PortletURL actionURL = response.createActionURL();
181 			ScriptPostProcess processor = new ScriptPostProcess();
182 			processor.setInitalPage(page);
183 			processor.postProcessPage(actionURL, ACTION_PARAMETER_SSOPROXY);
184 			String finalPage = processor.getFinalizedPage();
185 			
186 			// Write the page
187 			response.getWriter().println(finalPage);
188         
189         }
190         catch (SSOException e)
191         {
192         	response.getWriter().println("<P>Error rendering page. Error message<BR>" + e.getMessage() + "</P>");
193         	
194         	this.destinationURL ="";   
195         }          
196     }
197     
198 
199     public void doEdit(RenderRequest request, RenderResponse response)
200     throws PortletException, IOException
201     {
202          super.doEdit(request, response);
203     }
204 
205     /*
206      * Helper methods
207      */
208     private Subject getSubject()
209     {
210         AccessControlContext context = AccessController.getContext();
211         return JSSubject.getSubject(context);         
212     }
213     
214     /*
215     private String getContentCharSet(InputStream is) throws IOException
216     {
217         if (!is.markSupported())
218         {
219             return null;
220         }
221 
222         byte[] buf = new byte[BLOCK_SIZE];
223         try
224         {
225             is.read(buf, 0, BLOCK_SIZE);
226             String content = new String(buf, "ISO-8859-1");
227             String lowerCaseContent = content.toLowerCase();
228             int startIndex = lowerCaseContent.indexOf("<head");
229             if (startIndex == -1)
230             {
231                 startIndex = 0;
232             }
233             int endIndex = lowerCaseContent.indexOf("</head");
234             if (endIndex == -1)
235             {
236                 endIndex = content.length();
237             }
238             content = content.substring(startIndex, endIndex);
239 
240             StringTokenizer st = new StringTokenizer(content, "<>");
241             while (st.hasMoreTokens())
242             {
243                 String element = st.nextToken();
244                 String lowerCaseElement = element.toLowerCase();
245                 if (lowerCaseElement.startsWith("meta") && lowerCaseElement.indexOf("content-type") > 0)
246                 {
247                     StringTokenizer est = new StringTokenizer(element, " =\"\';");
248                     while (est.hasMoreTokens())
249                     {
250                         if (est.nextToken().equalsIgnoreCase("charset"))
251                         {
252                             if (est.hasMoreTokens())
253                             {
254                                 is.reset();
255                                 return est.nextToken();
256                             }
257                         }
258                     }
259                 }
260             }
261         }
262         catch (IOException e)
263         {
264         }
265 
266         is.reset();
267 
268         return null;
269     }
270     */
271    
272 }