File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\security\BasicAuthenticationFilter.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 package hudson.security;
25
26 import hudson.model.User;
27 import jenkins.model.Jenkins;
28 import hudson.util.Scrambler;
29 import jenkins.security.ApiTokenProperty;
30 import org.acegisecurity.context.SecurityContextHolder;
31 import org.kohsuke.stapler.StaplerRequest;
32 import org.kohsuke.stapler.StaplerResponse;
33
34 import javax.servlet.Filter;
35 import javax.servlet.FilterChain;
36 import javax.servlet.FilterConfig;
37 import javax.servlet.RequestDispatcher;
38 import javax.servlet.ServletContext;
39 import javax.servlet.ServletException;
40 import javax.servlet.ServletRequest;
41 import javax.servlet.ServletResponse;
42 import javax.servlet.http.HttpServletRequest;
43 import javax.servlet.http.HttpServletResponse;
44 import java.io.IOException;
45 import java.net.URLEncoder;
46
47 /**
48 * Implements the dual authentcation mechanism.
49 *
50 * <p>
51 * Jenkins supports both the HTTP basic authentication and the form-based authentication.
52 * The former is for scripted clients, and the latter is for humans. Unfortunately,
53 * because the servlet spec does not allow us to programatically authenticate users,
54 * we need to rely on some hack to make it work, and this is the class that implements
55 * that hack.
56 *
57 * <p>
58 * When an HTTP request arrives with an HTTP basic auth header, this filter detects
59 * that and emulate an invocation of <tt>/j_security_check</tt>
60 * (see <a href="http://mail-archives.apache.org/mod_mbox/tomcat-users/200105.mbox/%3C9005C0C9C85BD31181B20060085DAC8B10C8EF@tuvi.andmevara.ee%3E">this page</a> for the original technique.)
61 *
62 * <p>
63 * This causes the container to perform authentication, but there's no way
64 * to find out whether the user has been successfully authenticated or not.
65 * So to find this out, we then redirect the user to
66 * {@link jenkins.model.Jenkins#doSecured(StaplerRequest, StaplerResponse) <tt>/secured/...</tt> page}.
67 *
68 * <p>
69 * The handler of the above URL checks if the user is authenticated,
70 * and if not report an HTTP error code. Otherwise the user is
71 * redirected back to the original URL, where the request is served.
72 *
73 * <p>
74 * So all in all, the redirection works like <tt>/abc/def</tt> -> <tt>/secured/abc/def</tt>
75 * -> <tt>/abc/def</tt>.
76 *
77 * <h2>Notes</h2>
78 * <ul>
79 * <li>
80 * The technique of getting a request dispatcher for <tt>/j_security_check</tt> may not
81 * work for all containers, but so far that seems like the only way to make this work.
82 * <li>
83 * This A->B->A redirect is a cyclic redirection, so we need to watch out for clients
84 * that detect this as an error.
85 * </ul>
86 *
87 * @author Kohsuke Kawaguchi
88 */
89 public class BasicAuthenticationFilter implements Filter {
90 private ServletContext servletContext;
91
92 public void init(FilterConfig filterConfig) throws ServletException {
93 servletContext = filterConfig.getServletContext();
94 }
95
96 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
97 HttpServletRequest req = (HttpServletRequest) request;
98 HttpServletResponse rsp = (HttpServletResponse) response;
99 String authorization = req.getHeader("Authorization");
100
101 String path = req.getServletPath();
102 if(authorization==null || req.getUserPrincipal() !=null || path.startsWith("/secured/")
103 || !Jenkins.getInstance().isUseSecurity()) {
104 // normal requests, or security not enabled
105 if(req.getUserPrincipal()!=null) {
106 // before we route this request, integrate the container authentication
107 // to Acegi. For anonymous users that doesn't have user principal,
108 // AnonymousProcessingFilter that follows this should create
109 // an Authentication object.
110 SecurityContextHolder.getContext().setAuthentication(new ContainerAuthentication(req));
111 }
112 try {
113 chain.doFilter(request,response);
114 } finally {
115 SecurityContextHolder.clearContext();
116 }
117 return;
118 }
119
120 // authenticate the user
121 String username = null;
122 String password = null;
123 String uidpassword = Scrambler.descramble(authorization.substring(6));
124 int idx = uidpassword.indexOf(':');
125 if (idx >= 0) {
126 username = uidpassword.substring(0, idx);
127 password = uidpassword.substring(idx+1);
128 }
129
130 if(username==null) {
131 rsp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
132 rsp.setHeader("WWW-Authenticate","Basic realm=\"Jenkins user\"");
133 return;
134 }
135
136 {// attempt to authenticate as API token
137 User u = User.get(username);
138 ApiTokenProperty t = u.getProperty(ApiTokenProperty.class);
139 if (t!=null && t.matchesPassword(password)) {
140 SecurityContextHolder.getContext().setAuthentication(u.impersonate());
141 try {
142 chain.doFilter(request,response);
143 } finally {
144 SecurityContextHolder.clearContext();
145 }
146 return;
147 }
148 }
149
150
151 path = req.getContextPath()+"/secured"+path;
152 String q = req.getQueryString();
153 if(q!=null)
154 path += '?'+q;
155
156 // prepare a redirect
157 rsp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
158 rsp.setHeader("Location",path);
159
160 // ... but first let the container authenticate this request
161 RequestDispatcher d = servletContext.getRequestDispatcher("/j_security_check?j_username="+
162 URLEncoder.encode(username,"UTF-8")+"&j_password="+URLEncoder.encode(password,"UTF-8"));
163 d.include(req,rsp);
164 }
165
166 //public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
167 // HttpServletRequest req = (HttpServletRequest) request;
168 // String authorization = req.getHeader("Authorization");
169 //
170 // String path = req.getServletPath();
171 // if(authorization==null || req.getUserPrincipal()!=null || path.startsWith("/secured/")) {
172 // chain.doFilter(request,response);
173 // } else {
174 // if(req.getQueryString()!=null)
175 // path += req.getQueryString();
176 // ((HttpServletResponse)response).sendRedirect(req.getContextPath()+"/secured"+path);
177 // }
178 //}
179
180 public void destroy() {
181 }
182 }
183