James Moger
2014-06-12 ef4a461f2fca3f445afb16718448b14f2b57e810
commit | author | age
ca9d0f 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  */
7bf6e1 16 package com.gitblit.servlet;
ca9d0f 17
JM 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.FilterChain;
ec2456 25 import javax.servlet.FilterConfig;
ca9d0f 26 import javax.servlet.ServletException;
JM 27 import javax.servlet.ServletRequest;
28 import javax.servlet.ServletResponse;
29 import javax.servlet.http.HttpServletRequest;
1f596c 30 import javax.servlet.http.HttpServletRequestWrapper;
ca9d0f 31 import javax.servlet.http.HttpServletResponse;
JM 32 import javax.servlet.http.HttpSession;
33
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
7bf6e1 37 import com.gitblit.Constants;
65d5bb 38 import com.gitblit.dagger.DaggerFilter;
04a985 39 import com.gitblit.manager.IAuthenticationManager;
ca9d0f 40 import com.gitblit.models.UserModel;
b5798e 41 import com.gitblit.utils.DeepCopier;
ca9d0f 42 import com.gitblit.utils.StringUtils;
65d5bb 43
JM 44 import dagger.ObjectGraph;
ca9d0f 45
JM 46 /**
47  * The AuthenticationFilter is a servlet filter that preprocesses requests that
48  * match its url pattern definition in the web.xml file.
699e71 49  *
ca9d0f 50  * http://en.wikipedia.org/wiki/Basic_access_authentication
699e71 51  *
ca9d0f 52  * @author James Moger
699e71 53  *
ca9d0f 54  */
65d5bb 55 public abstract class AuthenticationFilter extends DaggerFilter {
ca9d0f 56
37fa66 57     protected static final String CHALLENGE = "Basic realm=\"" + Constants.NAME + "\"";
ca9d0f 58
JM 59     protected static final String SESSION_SECURED = "com.gitblit.secured";
60
61     protected transient Logger logger = LoggerFactory.getLogger(getClass());
62
65d5bb 63     protected IAuthenticationManager authenticationManager;
cacf8b 64
65d5bb 65     @Override
ec2456 66     protected void inject(ObjectGraph dagger, FilterConfig filterConfig) {
65d5bb 67         this.authenticationManager = dagger.get(IAuthenticationManager.class);
cacf8b 68     }
JM 69
ca9d0f 70     /**
JM 71      * doFilter does the actual work of preprocessing the request to ensure that
72      * the user may proceed.
699e71 73      *
ca9d0f 74      * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
JM 75      *      javax.servlet.ServletResponse, javax.servlet.FilterChain)
76      */
77     @Override
78     public abstract void doFilter(final ServletRequest request, final ServletResponse response,
79             final FilterChain chain) throws IOException, ServletException;
699e71 80
3983a6 81     /**
JM 82      * Allow the filter to require a client certificate to continue processing.
699e71 83      *
3983a6 84      * @return true, if a client certificate is required
JM 85      */
86     protected boolean requiresClientCertificate() {
87         return false;
88     }
ca9d0f 89
JM 90     /**
91      * Returns the full relative url of the request.
699e71 92      *
ca9d0f 93      * @param httpRequest
JM 94      * @return url
95      */
96     protected String getFullUrl(HttpServletRequest httpRequest) {
97         String servletUrl = httpRequest.getContextPath() + httpRequest.getServletPath();
98         String url = httpRequest.getRequestURI().substring(servletUrl.length());
99         String params = httpRequest.getQueryString();
100         if (url.length() > 0 && url.charAt(0) == '/') {
101             url = url.substring(1);
102         }
103         String fullUrl = url + (StringUtils.isEmpty(params) ? "" : ("?" + params));
104         return fullUrl;
105     }
106
107     /**
108      * Returns the user making the request, if the user has authenticated.
699e71 109      *
ca9d0f 110      * @param httpRequest
JM 111      * @return user
112      */
113     protected UserModel getUser(HttpServletRequest httpRequest) {
04a985 114         UserModel user = authenticationManager.authenticate(httpRequest, requiresClientCertificate());
37fa66 115         return user;
ca9d0f 116     }
JM 117
118     /**
119      * Taken from Jetty's LoginAuthenticator.renewSessionOnAuthentication()
120      */
121     protected void newSession(HttpServletRequest request, HttpServletResponse response) {
122         HttpSession oldSession = request.getSession(false);
123         if (oldSession != null && oldSession.getAttribute(SESSION_SECURED) == null) {
124             synchronized (this) {
125                 Map<String, Object> attributes = new HashMap<String, Object>();
126                 Enumeration<String> e = oldSession.getAttributeNames();
127                 while (e.hasMoreElements()) {
128                     String name = e.nextElement();
129                     attributes.put(name, oldSession.getAttribute(name));
130                     oldSession.removeAttribute(name);
131                 }
132                 oldSession.invalidate();
133
134                 HttpSession newSession = request.getSession(true);
135                 newSession.setAttribute(SESSION_SECURED, Boolean.TRUE);
136                 for (Map.Entry<String, Object> entry : attributes.entrySet()) {
137                     newSession.setAttribute(entry.getKey(), entry.getValue());
138                 }
139             }
140         }
141     }
142
143     /**
144      * Wraps a standard HttpServletRequest and overrides user principal methods.
145      */
1f596c 146     public static class AuthenticatedRequest extends HttpServletRequestWrapper {
ca9d0f 147
JM 148         private UserModel user;
149
150         public AuthenticatedRequest(HttpServletRequest req) {
151             super(req);
b5798e 152             user = DeepCopier.copy(UserModel.ANONYMOUS);
ca9d0f 153         }
efe8ec 154
ca9d0f 155         UserModel getUser() {
JM 156             return user;
157         }
158
159         void setUser(UserModel user) {
160             this.user = user;
161         }
162
163         @Override
164         public String getRemoteUser() {
165             return user.username;
166         }
167
168         @Override
169         public boolean isUserInRole(String role) {
170             if (role.equals(Constants.ADMIN_ROLE)) {
7f7051 171                 return user.canAdmin();
ca9d0f 172             }
efe8ec 173             // Gitblit does not currently use actual roles in the traditional
JM 174             // servlet container sense.  That is the reason this is marked
175             // deprecated, but I may want to revisit this.
7127df 176             return user.hasRepositoryPermission(role);
ca9d0f 177         }
JM 178
179         @Override
180         public Principal getUserPrincipal() {
181             return user;
182         }
183     }
c5c641 184 }