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