1 package com.atlassian.seraph.filter;
2
3 import com.atlassian.seraph.RequestParameterConstants;
4 import com.atlassian.seraph.auth.Authenticator;
5 import com.atlassian.seraph.config.SecurityConfig;
6 import com.atlassian.seraph.config.SecurityConfigFactory;
7 import com.atlassian.seraph.elevatedsecurity.ElevatedSecurityGuard;
8 import com.atlassian.seraph.util.RedirectUtils;
9 import org.apache.log4j.Logger;
10
11 import java.io.IOException;
12 import java.net.URI;
13 import java.net.URISyntaxException;
14 import java.security.Principal;
15 import javax.servlet.Filter;
16 import javax.servlet.FilterChain;
17 import javax.servlet.FilterConfig;
18 import javax.servlet.ServletException;
19 import javax.servlet.ServletRequest;
20 import javax.servlet.ServletResponse;
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletRequestWrapper;
23 import javax.servlet.http.HttpServletResponse;
24 import javax.servlet.http.HttpSession;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 public abstract class BaseLoginFilter implements Filter
49 {
50 private static final Logger log = Logger.getLogger(BaseLoginFilter.class);
51
52 private FilterConfig filterConfig = null;
53 protected static final String ALREADY_FILTERED = "loginfilter.already.filtered";
54 public static final String LOGIN_SUCCESS = "success";
55 public static final String LOGIN_FAILED = "failed";
56 public static final String LOGIN_ERROR = "error";
57 public static final String LOGIN_NOATTEMPT = null;
58 public static final String OS_AUTHSTATUS_KEY = "os_authstatus";
59 private SecurityConfig securityConfig = null;
60
61 public BaseLoginFilter()
62 {
63 super();
64 }
65
66 public void init(final FilterConfig config)
67 {
68 this.filterConfig = config;
69 }
70
71 public void destroy()
72 {
73 filterConfig = null;
74 }
75
76
77
78
79
80
81 public FilterConfig getFilterConfig()
82 {
83 return filterConfig;
84 }
85
86
87
88
89
90
91 public void setFilterConfig(final FilterConfig filterConfig)
92 {
93 if (filterConfig != null)
94 {
95 init(filterConfig);
96 }
97 }
98
99 public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain)
100 throws IOException, ServletException
101 {
102 final String METHOD = "doFilter : ";
103 final boolean dbg = log.isDebugEnabled();
104
105
106 HttpServletRequest httpServletRequest = new SecurityHttpRequestWrapper((HttpServletRequest) servletRequest);
107 HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
108
109 if (servletRequest.getAttribute(ALREADY_FILTERED) == null && getSecurityConfig().getController().isSecurityEnabled())
110 {
111 httpServletRequest.setAttribute(ALREADY_FILTERED, Boolean.TRUE);
112 httpServletRequest.setAttribute(OS_AUTHSTATUS_KEY, LOGIN_NOATTEMPT);
113
114 if (dbg)
115 {
116 log.debug(METHOD + "____ Attempting login for : '" + getRequestUrl(httpServletRequest) + "'");
117 }
118
119
120
121 String status = login(httpServletRequest, httpServletResponse);
122 httpServletRequest.setAttribute(OS_AUTHSTATUS_KEY, status);
123 if (dbg)
124 {
125 final String userName = httpServletRequest.getRemoteUser();
126 log.debug(METHOD + "Login completed for '" + userName + "' - " + OS_AUTHSTATUS_KEY + " = '" + status + "'");
127 }
128
129
130 if (LOGIN_SUCCESS.equals(status) && redirectToOriginalDestination(httpServletRequest, httpServletResponse))
131 {
132 return;
133 }
134
135 if (status == LOGIN_NOATTEMPT)
136 {
137 issuePossibleRedirectIfUserIsAlreadyLoggedIn(httpServletRequest, httpServletResponse);
138 }
139 }
140 filterChain.doFilter(httpServletRequest, httpServletResponse);
141 }
142
143 private String getRequestUrl(final HttpServletRequest httpServletRequest)
144 {
145 return httpServletRequest.getServletPath() +
146 (httpServletRequest.getPathInfo() == null ? "" : httpServletRequest.getPathInfo()) +
147 (httpServletRequest.getQueryString() == null ? "" : "?" + httpServletRequest.getQueryString());
148 }
149
150 private void issuePossibleRedirectIfUserIsAlreadyLoggedIn(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse)
151 throws IOException
152 {
153
154
155
156
157
158
159
160 if (httpServletRequest.getParameterMap().get(RequestParameterConstants.OS_DESTINATION) != null)
161 {
162 Principal principal = getAuthenticator().getUser(httpServletRequest, httpServletResponse);
163 if (principal != null)
164 {
165 HttpSession session = httpServletRequest.getSession();
166 if (session != null && session.getAttribute(SecurityConfigFactory.getInstance().getOriginalURLKey()) == null)
167 {
168 redirectToOriginalDestination(httpServletRequest, httpServletResponse);
169 }
170 }
171 }
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191 public abstract String login(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse);
192
193
194
195
196
197
198 class SecurityHttpRequestWrapper extends HttpServletRequestWrapper
199 {
200 private HttpServletRequest delegateHttpServletRequest;
201
202 public SecurityHttpRequestWrapper(final HttpServletRequest delegateHttpServletRequest)
203 {
204 super(delegateHttpServletRequest);
205 this.delegateHttpServletRequest = delegateHttpServletRequest;
206 }
207
208 public String getRemoteUser()
209 {
210 Principal user = getUserPrincipal();
211 return (user == null) ? null : user.getName();
212 }
213
214 public Principal getUserPrincipal()
215 {
216 return getSecurityConfig().getAuthenticator().getUser(delegateHttpServletRequest);
217 }
218 }
219
220
221
222
223
224
225
226
227
228
229
230 protected boolean redirectToOriginalDestination(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse)
231 throws IOException
232 {
233 final String METHOD = "redirectToOriginalDestination : ";
234 final boolean dbg = log.isDebugEnabled();
235
236
237 String redirectURL = (String) httpServletRequest.getSession().getAttribute(getSecurityConfig().getOriginalURLKey());
238 if (redirectURL != null)
239 {
240
241 httpServletRequest.getSession().setAttribute(getSecurityConfig().getOriginalURLKey(), null);
242 }
243 else
244 {
245
246 redirectURL = httpServletRequest.getParameter(RequestParameterConstants.OS_DESTINATION);
247 }
248
249 if (redirectURL == null)
250 {
251 return false;
252 }
253
254
255 if (!getSecurityConfig().getRedirectPolicy().allowedRedirectDestination(redirectURL, httpServletRequest))
256 {
257
258 log.warn(METHOD + "Redirect request to '" + redirectURL + "' is not allowed. Will send user to the context root instead.");
259
260 redirectURL = "/";
261 }
262
263 if (!isAbsoluteUrl(redirectURL))
264 {
265
266
267 redirectURL = RedirectUtils.appendPathToContext(httpServletRequest.getContextPath(), redirectURL);
268 }
269
270 if (dbg)
271 {
272 log.debug(METHOD + "Login redirect to: " + redirectURL);
273 }
274
275 httpServletResponse.sendRedirect(redirectURL);
276 return true;
277 }
278
279 protected boolean isAbsoluteUrl(final String url)
280 {
281 try
282 {
283 URI uri = new URI(url);
284 return uri.isAbsolute();
285 }
286 catch (URISyntaxException e)
287 {
288 return false;
289 }
290 }
291
292 protected Authenticator getAuthenticator()
293 {
294 return getSecurityConfig().getAuthenticator();
295 }
296
297 protected ElevatedSecurityGuard getElevatedSecurityGuard()
298 {
299 return getSecurityConfig().getElevatedSecurityGuard();
300 }
301
302 protected SecurityConfig getSecurityConfig()
303 {
304 if (securityConfig == null)
305 {
306 securityConfig = (SecurityConfig) filterConfig.getServletContext().getAttribute(SecurityConfig.STORAGE_KEY);
307 }
308 return securityConfig;
309 }
310 }