1 package com.atlassian.seraph.filter;
2
3 import java.io.IOException;
4 import java.security.Principal;
5 import java.util.HashSet;
6 import java.util.Iterator;
7 import java.util.Set;
8
9 import javax.servlet.Filter;
10 import javax.servlet.FilterChain;
11 import javax.servlet.FilterConfig;
12 import javax.servlet.ServletException;
13 import javax.servlet.ServletRequest;
14 import javax.servlet.ServletResponse;
15 import javax.servlet.http.HttpServletRequest;
16 import javax.servlet.http.HttpServletResponse;
17
18 import org.apache.log4j.Category;
19
20 import com.atlassian.seraph.SecurityService;
21 import com.atlassian.seraph.auth.AuthenticationContext;
22 import com.atlassian.seraph.config.SecurityConfig;
23 import com.atlassian.seraph.config.SecurityConfigFactory;
24 import com.atlassian.seraph.util.RedirectUtils;
25
26
27
28
29
30
31 public class SecurityFilter implements Filter
32 {
33 private FilterConfig config = null;
34 private SecurityConfig securityConfig = null;
35
36 private static final Category log = Category.getInstance(SecurityFilter.class);
37 private static final String ALREADY_FILTERED = "os_securityfilter_already_filtered";
38 public static final String ORIGINAL_URL = "atlassian.core.seraph.original.url";
39
40 public void init(FilterConfig config)
41 {
42
43 this.config = config;
44
45 String configFileLocation = null;
46
47 if (config.getInitParameter("config.file") != null)
48 {
49 configFileLocation = config.getInitParameter("config.file");
50 log.debug("Security config file location: " + configFileLocation);
51 }
52
53 securityConfig = SecurityConfigFactory.getInstance(configFileLocation);
54 config.getServletContext().setAttribute(SecurityConfig.STORAGE_KEY, securityConfig);
55 }
56
57 public void destroy()
58 {
59
60 securityConfig.destroy();
61 securityConfig = null;
62 config = null;
63 }
64
65
66
67
68
69 public FilterConfig getFilterConfig()
70 {
71 return config;
72 }
73
74
75
76
77
78 public void setFilterConfig(FilterConfig filterConfig)
79 {
80 if (filterConfig != null)
81 init(filterConfig);
82 }
83
84 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
85 throws IOException, ServletException
86 {
87 if (req.getAttribute(ALREADY_FILTERED) != null || !getSecurityConfig().getController().isSecurityEnabled())
88 {
89 chain.doFilter(req, res);
90 return;
91 }
92 else
93 {
94 req.setAttribute(ALREADY_FILTERED, Boolean.TRUE);
95 }
96
97
98
99 if (req.getAttribute(BaseLoginFilter.ALREADY_FILTERED) == null)
100 {
101 log.warn("LoginFilter not yet applied to this request - terminating filter chain");
102 return;
103 }
104
105 HttpServletRequest request = (HttpServletRequest) req;
106 HttpServletResponse response = (HttpServletResponse) res;
107
108 String originalURL = request.getServletPath() +
109 (request.getPathInfo() == null ? "" : request.getPathInfo()) +
110 (request.getQueryString() == null ? "" : "?" + request.getQueryString());
111
112
113
114 request.setAttribute(SecurityFilter.ORIGINAL_URL, originalURL);
115 if (log.isDebugEnabled())
116 log.debug("Storing the originally requested URL (" + SecurityFilter.ORIGINAL_URL + "=" + originalURL + ")");
117
118 Set requiredRoles = new HashSet();
119
120
121 for (Iterator iterator = getSecurityConfig().getServices().iterator(); iterator.hasNext();)
122 {
123 SecurityService service = (SecurityService) iterator.next();
124
125 Set serviceRoles = service.getRequiredRoles(request);
126 requiredRoles.addAll(serviceRoles);
127 }
128
129 if (log.isDebugEnabled()) {
130 log.debug("requiredRoles = " + requiredRoles);
131 }
132
133
134 boolean needAuth = false;
135
136
137 Principal user = getSecurityConfig().getAuthenticator().getUser(request, response);
138
139
140 boolean basicAuthentication = RedirectUtils.isBasicAuthentication(request, getSecurityConfig().getAuthType());
141
142
143 if (basicAuthentication && user == null)
144 {
145 log.debug("Basic authentication requested.");
146 return;
147 }
148
149
150 getAuthenticationContext().setUser(user);
151
152
153
154 for (Iterator iterator = requiredRoles.iterator(); iterator.hasNext();)
155 {
156 String role = (String) iterator.next();
157
158
159
160 if (!getSecurityConfig().getRoleMapper().hasRole(user, request, role))
161 {
162 log.info("User '" + user + "' needs (and lacks) role '" + role + "' to access " + originalURL);
163 needAuth = true;
164 }
165 }
166
167
168 if (request.getServletPath() != null && request.getServletPath().equals(getSecurityConfig().getLoginURL()))
169 {
170 log.debug("Login page requested so no additional authorization required.");
171 needAuth = false;
172 }
173
174
175 if (needAuth)
176 {
177 if (log.isDebugEnabled())
178 log.debug("Need Authentication: Redirecting to: " + getSecurityConfig().getLoginURL() + " from: " + originalURL);
179
180 request.getSession().setAttribute(getSecurityConfig().getOriginalURLKey(), originalURL);
181
182 if (!response.isCommitted())
183 {
184 response.sendRedirect(RedirectUtils.getLoginUrl(request));
185 }
186 return;
187 }
188 else
189 {
190 try
191 {
192 chain.doFilter(req, res);
193 }
194 finally
195 {
196
197 getAuthenticationContext().clearUser();
198 }
199 }
200 }
201
202 protected SecurityConfig getSecurityConfig() {
203
204 if (securityConfig == null)
205 {
206 securityConfig = (SecurityConfig) config.getServletContext().getAttribute(SecurityConfig.STORAGE_KEY);
207 }
208 return securityConfig;
209 }
210
211 protected AuthenticationContext getAuthenticationContext() {
212 return getSecurityConfig().getAuthenticationContext();
213 }
214
215 }