Rev 1072 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
924 | dev | 1 | package ak.hostadmiral.core.servlet; |
919 | dev | 2 | |
3 | import java.util.List; |
||
4 | import java.util.ArrayList; |
||
5 | import java.util.StringTokenizer; |
||
6 | import java.io.IOException; |
||
7 | import java.net.URLEncoder; |
||
8 | import java.security.Principal; |
||
9 | import java.security.AccessControlException; |
||
10 | |||
11 | import javax.servlet.Filter; |
||
12 | import javax.servlet.FilterChain; |
||
13 | import javax.servlet.FilterConfig; |
||
14 | import javax.servlet.ServletException; |
||
15 | import javax.servlet.ServletRequest; |
||
16 | import javax.servlet.ServletResponse; |
||
17 | import javax.servlet.http.HttpSession; |
||
18 | import javax.servlet.http.HttpServletRequest; |
||
19 | import javax.servlet.http.HttpServletResponse; |
||
20 | |||
21 | import org.apache.log4j.Logger; |
||
22 | |||
23 | import ak.backpath.BackPath; |
||
24 | |||
1072 | dev | 25 | import ak.hostadmiral.util.ModelException; |
26 | import ak.hostadmiral.core.servlet.LoginInfo; |
||
924 | dev | 27 | import ak.hostadmiral.core.model.User; |
1072 | dev | 28 | import ak.hostadmiral.core.model.UserManager; |
919 | dev | 29 | |
30 | /** |
||
31 | * Ensures that user is logged in to the system to process its request. |
||
32 | */ |
||
33 | public class LoginFilter |
||
34 | implements Filter |
||
35 | { |
||
36 | private static final Logger logger = Logger.getLogger(LoginFilter.class); |
||
37 | |||
38 | private FilterConfig filterConfig; |
||
39 | private String loginUrl; |
||
40 | private String loginServlet; |
||
41 | private List passUrls = new ArrayList(); |
||
42 | private List passMasks = new ArrayList(); |
||
43 | |||
44 | public void init(FilterConfig filterConfig) |
||
45 | throws ServletException |
||
46 | { |
||
47 | // get config |
||
48 | this.filterConfig = filterConfig; |
||
49 | |||
50 | if(filterConfig == null) |
||
51 | throw new ServletException("No configuration for the filter"); |
||
52 | |||
53 | // get login url |
||
54 | loginUrl = filterConfig.getInitParameter("loginUrl"); |
||
55 | |||
56 | if(loginUrl == null) |
||
57 | throw new ServletException("No login URL specified"); |
||
58 | |||
59 | // ensure it's absolute path |
||
60 | if(!loginUrl.startsWith("/")) |
||
61 | loginUrl = "/" + loginUrl; |
||
62 | |||
63 | // get servlet part ot the url |
||
64 | int qPos = loginUrl.indexOf("?"); |
||
65 | |||
66 | if(qPos < 0) |
||
67 | loginServlet = loginUrl; |
||
68 | else |
||
69 | loginServlet = loginUrl.substring(0, qPos); |
||
70 | |||
71 | // get pass through URLs |
||
72 | String passUrlsStr = filterConfig.getInitParameter("passUrls"); |
||
73 | if(passUrlsStr != null) { |
||
74 | String[] urls = passUrlsStr.split("\\s*;\\s*"); |
||
75 | |||
76 | for(int i = 0; i < urls.length; i++) { |
||
77 | if(urls[i].endsWith("*")) { |
||
78 | passMasks.add(urls[i].substring(0, urls[i].length()-1)); |
||
79 | } |
||
80 | else { |
||
81 | passUrls.add(urls[i]); |
||
82 | } |
||
83 | } |
||
84 | } |
||
85 | |||
86 | // avoid loop |
||
87 | if(!isPassThrough(loginServlet)) { |
||
88 | passUrls.add(loginServlet); |
||
89 | } |
||
90 | } |
||
91 | |||
92 | private boolean isPassThrough(String url) |
||
93 | { |
||
94 | for(int i = 0; i < passUrls.size(); i++) { |
||
95 | if(url.equals((String)passUrls.get(i))) return true; |
||
96 | } |
||
97 | |||
98 | for(int i = 0; i < passMasks.size(); i++) { |
||
99 | if(url.startsWith((String)passMasks.get(i))) return true; |
||
100 | } |
||
101 | |||
102 | return false; |
||
103 | } |
||
104 | |||
105 | public void doFilter(ServletRequest request, ServletResponse response, |
||
106 | FilterChain chain) |
||
107 | throws IOException, ServletException |
||
108 | { |
||
109 | boolean processNext; |
||
110 | |||
111 | if(!(request instanceof HttpServletRequest)) |
||
112 | throw new ServletException("Do not know how to handle non-HTTP requests"); |
||
113 | if(!(response instanceof HttpServletResponse)) |
||
1222 | dev | 114 | throw new ServletException("Do not know how to handle non-HTTP responses"); |
919 | dev | 115 | |
116 | HttpServletRequest httpRequest = (HttpServletRequest)request; |
||
117 | HttpServletResponse httpResponse = (HttpServletResponse)response; |
||
118 | |||
119 | logger.debug("Requested " + httpRequest.getServletPath()); |
||
120 | |||
121 | if(isPassThrough(httpRequest.getServletPath())) { |
||
122 | processNext = true; |
||
123 | logger.debug("pass through"); |
||
124 | } |
||
125 | else { |
||
126 | try { |
||
127 | HttpSession session = httpRequest.getSession(false); |
||
128 | |||
129 | if(session == null) |
||
130 | throw new AccessControlException("No session"); |
||
131 | |||
1056 | dev | 132 | Object userObj = session.getAttribute(SessionKeys.USER); |
1072 | dev | 133 | if(userObj == null) { |
134 | // try to relogin |
||
135 | Object loginInfoObj = session.getAttribute(SessionKeys.LOGIN_INFO); |
||
136 | if(loginInfoObj == null) |
||
137 | throw new AccessControlException("No user"); |
||
919 | dev | 138 | |
1072 | dev | 139 | if(!(loginInfoObj instanceof LoginInfo)) |
140 | throw new ServletException( |
||
141 | "Wrong type of login info information: " |
||
142 | + loginInfoObj.getClass().getName()); |
||
919 | dev | 143 | |
1072 | dev | 144 | try { |
145 | userObj = UserManager.getInstance().get(((LoginInfo)loginInfoObj).getId()); |
||
146 | } |
||
147 | catch(ModelException ex) { |
||
148 | throw new AccessControlException("No user"); |
||
149 | } |
||
150 | |||
151 | if(userObj == null) |
||
152 | throw new AccessControlException("No user"); |
||
153 | |||
154 | session.setAttribute(SessionKeys.USER, userObj); |
||
155 | logger.debug("User re-logined: " + userObj); |
||
156 | } |
||
157 | else { |
||
158 | if(!(userObj instanceof User)) |
||
159 | throw new ServletException( |
||
160 | "Wrong type of user information: " + userObj.getClass().getName()); |
||
161 | |||
162 | logger.debug("User found - OK"); |
||
163 | } |
||
164 | |||
919 | dev | 165 | processNext = true; |
166 | } |
||
167 | catch(AccessControlException ex) { |
||
168 | String redirectUrl; |
||
169 | try { |
||
170 | redirectUrl = httpRequest.getContextPath() + loginUrl |
||
171 | + BackPath.findBackPath(httpRequest).getForwardParams(); |
||
172 | } |
||
173 | catch(Exception ex2) { |
||
174 | logger.error("Cannot get forward redirect", ex2); |
||
175 | redirectUrl = httpRequest.getContextPath() + loginUrl; |
||
176 | } |
||
177 | |||
178 | logger.info("Redirect because of '" + ex.getMessage() + "' to " + redirectUrl); |
||
179 | httpResponse.sendRedirect(httpResponse.encodeRedirectURL(redirectUrl)); |
||
180 | |||
181 | processNext = false; |
||
182 | } |
||
183 | } |
||
184 | |||
185 | if(processNext) { // no problems found |
||
186 | chain.doFilter(request, response); |
||
187 | } |
||
188 | } |
||
189 | |||
190 | public void destroy() |
||
191 | { |
||
192 | } |
||
193 | } |