1 /*
2  * Copyright (c) 2010, University of Kent
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
11  * Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 1. Neither the name of the University of Kent nor the names of its
16  * contributors may be used to endorse or promote products derived from this
17  * software without specific prior written permission.
18  *
19  * 2. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.
23  *
24  * 3. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * 4. YOU AGREE THAT THE EXCLUSIONS IN PARAGRAPHS 2 AND 3 ABOVE ARE REASONABLE
34  * IN THE CIRCUMSTANCES.  IN PARTICULAR, YOU ACKNOWLEDGE (1) THAT THIS
35  * SOFTWARE HAS BEEN MADE AVAILABLE TO YOU FREE OF CHARGE, (2) THAT THIS
36  * SOFTWARE IS NOT "PRODUCT" QUALITY, BUT HAS BEEN PRODUCED BY A RESEARCH
37  * GROUP WHO DESIRE TO MAKE THIS SOFTWARE FREELY AVAILABLE TO PEOPLE WHO WISH
38  * TO USE IT, AND (3) THAT BECAUSE THIS SOFTWARE IS NOT OF "PRODUCT" QUALITY
39  * IT IS INEVITABLE THAT THERE WILL BE BUGS AND ERRORS, AND POSSIBLY MORE
40  * SERIOUS FAULTS, IN THIS SOFTWARE.
41  *
42  * 5. This license is governed, except to the extent that local laws
43  * necessarily apply, by the laws of England and Wales.
44  */
45 package org.zxid;
46 
47 import java.io.IOException;
48 
49 import javax.servlet.Filter;
50 import javax.servlet.FilterChain;
51 import javax.servlet.FilterConfig;
52 import javax.servlet.ServletException;
53 import javax.servlet.ServletRequest;
54 import javax.servlet.ServletResponse;
55 import javax.servlet.http.HttpServletRequest;
56 import javax.servlet.http.HttpServletResponse;
57 import javax.servlet.http.HttpSession;
58 
59 /**
60  * Checks whether a session has been established yet. If not the
61  * user will be redirected to the SSO servlet, requesting it to
62  * authenticate the user.
63  *
64  * @author Stijn Lievens
65  *
66  */
67 public class ZxidSSOFilter implements Filter {
68 
69   /**
70    * The location of the ZXID SSO servlet.
71    * Can be set with an init-parameter.
72    */
73   private String ssoServletLocation = "sso";
74 
75   // @Override // commented out for Java 1.5
destroy()76   public void destroy() {
77   }
78 
79   /**
80    * Checks whether a session is already established. If it is then the filter does
81    * nothing but call the next one in the chain. Otherwise, the user is redirected
82    * to the ZXID SSO servlet.
83    */
84   //@Override // commented out for Java 1.5
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)85   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
86       throws IOException, ServletException {
87     HttpServletRequest req = (HttpServletRequest) request;
88     HttpSession ses = req.getSession(false);  // Important: do not allow automatic session.
89     if (ses != null) { // user was logged in. Continue
90       chain.doFilter(request, response);
91       return;
92     } else {
93     // No session was established yet, redirect to SSO servlet
94     ((HttpServletResponse) response).sendRedirect(ssoServletLocation + "?o=E&fr="
95         + getReturnURL(req));
96     }
97   }
98 
99   /**
100    * Sets the location of the SSO servlet.
101    */
102   //@Override // commented out for Java 1.5
init(FilterConfig config)103   public void init(FilterConfig config) throws ServletException {
104     if (config.getInitParameter("sso-servlet-location") != null) {
105       ssoServletLocation = config.getInitParameter("sso-servlet-location");
106     }
107   }
108 
109   /**
110    * Recreates the full URL that originally got the web client to the given
111    * request.  This takes into account changes to the request due to request
112    * dispatching.
113    *
114    * <p>Note that if the protocol is HTTP and the port number is 80 or if the
115    * protocol is HTTPS and the port number is 443, then the port number is not
116    * added to the return string as a convenience.</p>
117    */
118   // taken from: https://issues.apache.org/bugzilla/show_bug.cgi?id=28222
getReturnURL(HttpServletRequest request)119   private final static String getReturnURL(HttpServletRequest request) {
120       if (request == null){
121           throw new IllegalArgumentException("Cannot take null parameters.");
122       }
123 
124       String scheme = request.getScheme();
125       String serverName = request.getServerName();
126       int serverPort = request.getServerPort();
127 
128       /*
129        * Try to get the forwarder value first, only if it's empty fall back to the
130        * current value
131        */
132       String requestUri = (String) request.getAttribute("javax.servlet.forward.request_uri");
133       requestUri = (requestUri == null) ? request.getRequestURI() : requestUri;
134 
135       /*
136        * Try to get the forwarder value first, only if it's empty fall back to the
137        * current value.
138        */
139       String queryString = (String) request.getAttribute("javax.servlet.forward.query_string");
140       queryString = (queryString == null) ? request.getQueryString() : queryString;
141 
142       StringBuffer buffer = new StringBuffer();
143       buffer.append(scheme);
144       buffer.append("://");
145       buffer.append(serverName);
146 
147       //if not http:80 or https:443, then add the port number
148       if (!(scheme.equalsIgnoreCase("http") && serverPort == 80) &&
149           !(scheme.equalsIgnoreCase("https") && serverPort == 443)) {
150           buffer.append(":").append(String.valueOf(serverPort));
151       }
152 
153       buffer.append(requestUri);
154 
155       if (queryString != null) {
156           buffer.append("?");
157           buffer.append(queryString);
158       }
159 
160       return buffer.toString();
161   }
162 
163 }
164