1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package no.feide.moria.servlet;
22
23 import java.util.Properties;
24 import java.util.ResourceBundle;
25
26 import javax.servlet.RequestDispatcher;
27 import javax.servlet.http.Cookie;
28 import javax.servlet.http.HttpServlet;
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletResponse;
31
32 import no.feide.moria.controller.IllegalInputException;
33 import no.feide.moria.controller.InoperableStateException;
34 import no.feide.moria.controller.MoriaController;
35 import no.feide.moria.log.MessageLogger;
36
37 /***
38 * This servlet handles logout request. It will invalidate the SSO ticket in the
39 * underlying store and remove the cookie from the client. <p/> It uses two
40 * properties from the config:
41 * <dl>
42 * <dt>no.feide.moria.web.sso_cookie.name</dt>
43 * <dd>The the cookie name</dd>
44 * <dt>no.feide.moria.web.logout.url_param</dt>
45 * <dd>The name of the optional parameter in the request holding the redirect
46 * url.</dd>
47 * </dl>
48 * @author Lars Preben S. Arnesen <lars.preben.arnesen@conduct.no>
49 * @version $Revision: 1.17 $
50 */
51 public final class LogoutServlet
52 extends HttpServlet {
53
54 /***
55 * Serial version UID.
56 */
57 private static final long serialVersionUID = 5494943294819992935L;
58
59 /***
60 * The message logger used in this class.
61 */
62 private MessageLogger messageLogger;
63
64 /***
65 * The default redirect parameter name.<br>
66 * <br>
67 * Current value is <code>"redirect"</code>.
68 */
69 private static final String defaultRedirectParameterName = "redirect";
70
71 /***
72 * Default SSO cookie name, if not set in configuration.<br>
73 * <br>
74 * Current value is <code>"MoriaSSOCookie"</code>.
75 */
76 private static final String DEFAULT_SSO_COOKIE = "MoriaSSOCookie";
77
78
79 /***
80 * Intitiates the servlet.
81 */
82 public void init() {
83
84 messageLogger = new MessageLogger(LogoutServlet.class);
85 }
86
87
88 /***
89 * Handles the GET requests.
90 * @param request
91 * The HTTP request object.
92 * @param response
93 * The HTTP response object.
94 */
95 public void doGet(final HttpServletRequest request,
96 final HttpServletResponse response) {
97
98 final Properties config = RequestUtil.getConfig(getServletContext());
99
100
101 String ssoCookieName = config.getProperty(RequestUtil.PROP_COOKIE_SSO);
102
103 if (ssoCookieName == null || ssoCookieName.equals("")) {
104 ssoCookieName = DEFAULT_SSO_COOKIE;
105 messageLogger.logWarn("Parameter '" + RequestUtil.PROP_COOKIE_SSO + "' not set in config; using default value '" + ssoCookieName + "'");
106 }
107
108
109 final Cookie[] cookies = request.getCookies();
110 String cookieValue = null;
111 if (cookies != null)
112 cookieValue = RequestUtil.getCookieValue(ssoCookieName, cookies);
113
114
115 if ((cookies == null) ||
116 (cookieValue == null)) {
117 messageLogger.logWarn("Attempted logout of non-existing SSO session from host " + request.getRemoteAddr());
118 respond(config, request, response);
119 return;
120 }
121
122
123 final Cookie ssoCookie = RequestUtil.createCookie(config.getProperty(RequestUtil.PROP_COOKIE_SSO), cookieValue, 0);
124 response.addCookie(ssoCookie);
125
126
127 boolean controllerFailed = false;
128 try {
129 MoriaController.invalidateSSOTicket(cookieValue);
130 } catch (InoperableStateException ise) {
131 messageLogger.logWarn("Controller in inoperable state", cookieValue, ise);
132 controllerFailed = true;
133 } catch (IllegalInputException e) {
134 messageLogger.logWarn("Illegal SSO ticket value", cookieValue, e);
135 }
136 if (controllerFailed) {
137 final RequestDispatcher requestDispatcher = getServletContext().getNamedDispatcher("JSP-Error.JSP");
138
139 try {
140 requestDispatcher.forward(request, response);
141 } catch (Exception e) {
142 messageLogger.logCritical("Dispatch to JSP error JSP failed", cookieValue, e);
143 }
144
145 return;
146 }
147
148
149 respond(config, request, response);
150 }
151
152
153 /***
154 * Handles POST requests. Just calls doGet().
155 * @param request
156 * The HTTP request object.
157 * @param response
158 * The HTTP response object.
159 */
160 public void doPost(final HttpServletRequest request,
161 final HttpServletResponse response) {
162
163 doGet(request, response);
164 }
165
166
167 /***
168 * If the redirect URL is given in the request, redirect the user to the
169 * given URL. Otherwise display the default logout page.
170 * @param config
171 * The web module configuration.
172 * @param request
173 * The original request.
174 * @param response
175 * The response.
176 */
177 public void respond(final Properties config,
178 final HttpServletRequest request,
179 final HttpServletResponse response) {
180
181
182 String urlParam = config.getProperty(RequestUtil.PROP_LOGOUT_URL_PARAM);
183 if (urlParam == null) {
184 urlParam = defaultRedirectParameterName;
185 messageLogger.logWarn("Parameter '" + RequestUtil.PROP_LOGOUT_URL_PARAM + "' not set in config; using default value '" + urlParam + "'");
186 }
187
188
189 final String url = request.getParameter(urlParam);
190 if (url != null) {
191
192
193 response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
194 response.addHeader("Location", url);
195
196 } else {
197
198
199 String langFromCookie = null;
200 if (request.getCookies() != null)
201 langFromCookie = RequestUtil.getCookieValue((String) RequestUtil.getConfig(getServletContext()).get(RequestUtil.PROP_COOKIE_LANG), request.getCookies());
202 final ResourceBundle bundle = RequestUtil.getBundle("logout", request.getParameter("lang"), langFromCookie, null, request.getHeader("Accept-Language"), "en");
203 request.setAttribute("bundle", bundle);
204 final RequestDispatcher requestDispatcher = getServletContext().getNamedDispatcher("Logout.JSP");
205 try {
206 requestDispatcher.forward(request, response);
207 } catch (Exception e) {
208 messageLogger.logCritical("Dispatch to Logout JSP failed", e);
209 }
210 }
211 }
212 }