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