James Moger
2015-11-22 ed552ba47c02779c270ffd62841d6d1048dade70
commit | author | age
6e3481 1 /*
JM 2  * Copyright 2011 gitblit.com.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.gitblit.servlet;
17
18 import java.io.IOException;
19 import java.security.Principal;
20 import java.util.Enumeration;
21 import java.util.HashMap;
22 import java.util.Map;
23
24 import javax.servlet.Filter;
25 import javax.servlet.FilterChain;
26 import javax.servlet.FilterConfig;
27 import javax.servlet.ServletException;
28 import javax.servlet.ServletRequest;
29 import javax.servlet.ServletResponse;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletRequestWrapper;
32 import javax.servlet.http.HttpServletResponse;
33 import javax.servlet.http.HttpSession;
34
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 import com.gitblit.Constants;
39 import com.gitblit.Constants.Role;
40 import com.gitblit.manager.IAuthenticationManager;
41 import com.gitblit.models.UserModel;
42 import com.gitblit.utils.DeepCopier;
43 import com.gitblit.utils.StringUtils;
44
45 /**
46  * The AuthenticationFilter is a servlet filter that preprocesses requests that
47  * match its url pattern definition in the web.xml file.
48  *
49  * http://en.wikipedia.org/wiki/Basic_access_authentication
50  *
51  * @author James Moger
52  *
53  */
54 public abstract class AuthenticationFilter implements Filter {
55
56     protected static final String CHALLENGE = "Basic realm=\"" + Constants.NAME + "\"";
57
58     protected static final String SESSION_SECURED = "com.gitblit.secured";
59
60     protected transient Logger logger = LoggerFactory.getLogger(getClass());
61
62     protected IAuthenticationManager authenticationManager;
63
64     protected AuthenticationFilter(IAuthenticationManager authenticationManager) {
65         this.authenticationManager = authenticationManager;
66     }
67
68     @Override
69     public void init(FilterConfig filterConfig) throws ServletException {
70     }
71
72     @Override
73     public void destroy() {
74     }
75
76     /**
77      * doFilter does the actual work of preprocessing the request to ensure that
78      * the user may proceed.
79      *
80      * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
81      *      javax.servlet.ServletResponse, javax.servlet.FilterChain)
82      */
83     @Override
84     public abstract void doFilter(final ServletRequest request, final ServletResponse response,
85             final FilterChain chain) throws IOException, ServletException;
86
87     /**
88      * Allow the filter to require a client certificate to continue processing.
89      *
90      * @return true, if a client certificate is required
91      */
92     protected boolean requiresClientCertificate() {
93         return false;
94     }
95
96     /**
97      * Returns the full relative url of the request.
98      *
99      * @param httpRequest
100      * @return url
101      */
102     protected String getFullUrl(HttpServletRequest httpRequest) {
103         String servletUrl = httpRequest.getContextPath() + httpRequest.getServletPath();
104         String url = httpRequest.getRequestURI().substring(servletUrl.length());
105         String params = httpRequest.getQueryString();
106         if (url.length() > 0 && url.charAt(0) == '/') {
107             url = url.substring(1);
108         }
109         String fullUrl = url + (StringUtils.isEmpty(params) ? "" : ("?" + params));
110         return fullUrl;
111     }
112
113     /**
114      * Returns the user making the request, if the user has authenticated.
115      *
116      * @param httpRequest
117      * @return user
118      */
119     protected UserModel getUser(HttpServletRequest httpRequest) {
120         UserModel user = authenticationManager.authenticate(httpRequest, requiresClientCertificate());
121         return user;
122     }
123
124     /**
125      * Taken from Jetty's LoginAuthenticator.renewSessionOnAuthentication()
126      */
127     protected void newSession(HttpServletRequest request, HttpServletResponse response) {
128         HttpSession oldSession = request.getSession(false);
129         if (oldSession != null && oldSession.getAttribute(SESSION_SECURED) == null) {
130             synchronized (this) {
131                 Map<String, Object> attributes = new HashMap<String, Object>();
132                 Enumeration<String> e = oldSession.getAttributeNames();
133                 while (e.hasMoreElements()) {
134                     String name = e.nextElement();
135                     attributes.put(name, oldSession.getAttribute(name));
136                     oldSession.removeAttribute(name);
137                 }
138                 oldSession.invalidate();
139
140                 HttpSession newSession = request.getSession(true);
141                 newSession.setAttribute(SESSION_SECURED, Boolean.TRUE);
142                 for (Map.Entry<String, Object> entry : attributes.entrySet()) {
143                     newSession.setAttribute(entry.getKey(), entry.getValue());
144                 }
145             }
146         }
147     }
148
149     /**
150      * Wraps a standard HttpServletRequest and overrides user principal methods.
151      */
152     public static class AuthenticatedRequest extends HttpServletRequestWrapper {
153
154         private UserModel user;
155
156         public AuthenticatedRequest(HttpServletRequest req) {
157             super(req);
158             user = DeepCopier.copy(UserModel.ANONYMOUS);
159         }
160
161         UserModel getUser() {
162             return user;
163         }
164
165         void setUser(UserModel user) {
166             this.user = user;
167         }
168
169         @Override
170         public String getRemoteUser() {
171             return user.username;
172         }
173
174         @Override
175         public boolean isUserInRole(String role) {
176             if (role.equals(Role.ADMIN.getRole())) {
177                 return user.canAdmin();
178             }
179             // Gitblit does not currently use actual roles in the traditional
180             // servlet container sense.  That is the reason this is marked
181             // deprecated, but I may want to revisit this.
182             return user.hasRepositoryPermission(role);
183         }
184
185         @Override
186         public Principal getUserPrincipal() {
187             return user;
188         }
189     }
190 }