1   package com.atlassian.seraph.logout;
2   
3   import com.atlassian.seraph.auth.Authenticator;
4   import com.atlassian.seraph.auth.AuthenticatorException;
5   import com.atlassian.seraph.config.SecurityConfig;
6   import com.atlassian.seraph.config.SecurityConfigFactory;
7   import com.atlassian.seraph.config.SecurityConfigImpl;
8   
9   import java.io.IOException;
10  
11  import javax.servlet.ServletConfig;
12  import javax.servlet.ServletException;
13  import javax.servlet.http.HttpServlet;
14  import javax.servlet.http.HttpServletRequest;
15  import javax.servlet.http.HttpServletResponse;
16  
17  /**
18   * Seraph logout servlet. Configured via the 'logout.url' init param in seraph-config.xml. This servlet supports two logout behaviours:
19   * <ul>
20   * <li>If 'logout.url' is a relative path (e.g. <code>/logout.jsp</code> or <code>/logout.action<code>, this servlet
21   * simply redirects to it. The redirected-to page is responsible for calling {@link Authenticator#logout(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}.</li>
22   * <li>If 'logout.url' is absolute, this servlet logs the user out with {@link Authenticator#logout(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
23   * and then redirects to the absolute URL.</li>
24   * </ul>
25   */
26  public class LogoutServlet extends HttpServlet
27  {
28      private SecurityConfig securityConfig;
29  
30      public void init() throws ServletException
31      {
32          super.init();
33          securityConfig = SecurityConfigFactory.getInstance();
34      }
35  
36      public void init(final ServletConfig servletConfig) throws ServletException
37      {
38          super.init(servletConfig);
39          securityConfig = (SecurityConfig) servletConfig.getServletContext().getAttribute(SecurityConfigImpl.STORAGE_KEY);
40      }
41  
42      protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
43      {
44          if (isRelativeRedirect())
45          {
46              // Internal logout page; we rely on it to execute the logout logic in its own good time (eg., if the user confirms logout)
47              response.sendRedirect(request.getContextPath() + getSecurityConfig().getLogoutURL());
48          }
49          else
50          {
51              // External logout page; we execute logout logic immediately, and redirect to the external page.
52              try
53              {
54                  final Authenticator authenticator = getAuthenticator();
55                  authenticator.logout(request, response);
56              }
57              catch (final AuthenticatorException e)
58              {
59                  throw new ServletException("Seraph authenticator couldn't log out", e);
60              }
61              response.sendRedirect(getSecurityConfig().getLogoutURL());
62          }
63      }
64  
65      private boolean isRelativeRedirect()
66      {
67          return getSecurityConfig().getLogoutURL().indexOf("://") == -1;
68      }
69  
70      protected SecurityConfig getSecurityConfig()
71      {
72          return securityConfig;
73      }
74  
75      protected Authenticator getAuthenticator()
76      {
77          return getSecurityConfig().getAuthenticator();
78      }
79  }