KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > webservice > EjbWebServiceServlet


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.enterprise.webservice;
25
26 import java.io.IOException JavaDoc;
27 import java.util.logging.Logger JavaDoc;
28 import java.util.logging.Level JavaDoc;
29 import java.security.cert.X509Certificate JavaDoc;
30
31 import javax.servlet.ServletException JavaDoc;
32 import javax.servlet.http.HttpServlet JavaDoc;
33 import javax.servlet.http.HttpServletRequest JavaDoc;
34 import javax.servlet.http.HttpServletResponse JavaDoc;
35
36 import com.sun.enterprise.Switch;
37 import com.sun.ejb.Container;
38 import com.sun.enterprise.security.SecurityContext;
39 import com.sun.enterprise.deployment.Application;
40 import com.sun.enterprise.deployment.WebServiceEndpoint;
41 import com.sun.enterprise.webservice.EjbWebServiceDispatcher;
42 import com.sun.enterprise.webservice.EjbRuntimeEndpointInfo;
43 import com.sun.enterprise.webservice.WebServiceEjbEndpointRegistry;
44 import com.sun.enterprise.webservice.monitoring.WebServiceTesterServlet;
45 import com.sun.enterprise.webservice.monitoring.Endpoint;
46 import com.sun.enterprise.webservice.monitoring.EndpointType;
47 import com.sun.enterprise.webservice.monitoring.AuthenticationListener;
48 import com.sun.enterprise.webservice.monitoring.WebServiceEngineImpl;
49 import com.sun.web.security.WebPrincipal;
50 import com.sun.web.security.RealmAdapter;
51 import com.sun.logging.LogDomains;
52 import com.sun.enterprise.security.audit.AuditManager;
53 import com.sun.enterprise.security.audit.AuditManagerFactory;
54
55 import org.apache.catalina.Loader;
56 import org.apache.catalina.Globals;
57 import org.apache.catalina.util.Base64;
58
59 /**
60  * Servlet responsible for invoking EJB webservice endpoint.
61  *
62  * Most of this code used to be in
63  * com.sun.enterprise.webservice.EjbWebServiceValve.
64  *
65  * @author Qingqing Ouyang
66  * @author Kenneth Saks
67  * @author Jan Luehe
68  */

69 public class EjbWebServiceServlet extends HttpServlet JavaDoc {
70
71     private static Logger JavaDoc logger
72         = LogDomains.getLogger(LogDomains.EJB_LOGGER);
73     private static final Base64 base64Helper = new Base64();
74     private static final String JavaDoc AUTHORIZATION_HEADER = "authorization";
75
76     private static AuditManager auditManager =
77             AuditManagerFactory.getAuditManagerInstance();
78
79     protected void service(HttpServletRequest JavaDoc hreq, HttpServletResponse JavaDoc hresp)
80             throws ServletException JavaDoc, IOException JavaDoc {
81
82         boolean dispatch = true;
83
84         String JavaDoc requestUriRaw = hreq.getRequestURI();
85         String JavaDoc requestUri = (requestUriRaw.charAt(0) == '/') ?
86             requestUriRaw.substring(1) : requestUriRaw;
87         String JavaDoc query = hreq.getQueryString();
88
89         // check if it is a tester servlet invocation
90
if ("Tester".equalsIgnoreCase(query)) {
91             Endpoint endpoint = WebServiceEngineImpl.getInstance().getEndpoint(hreq.getRequestURL().toString());
92             if( (endpoint.getDescriptor().isSecure()) ||
93                 (endpoint.getDescriptor().getMessageSecurityBinding() != null) ) {
94                 // disable tester for secured services
95
String JavaDoc message = endpoint.getDescriptor().getWebService().getName() +
96                         " is a secured webservice; Tester feature is not supported for secured services";
97                 (new WsUtil()).writeInvalidMethodType(hresp, message);
98                 return;
99             }
100             if (endpoint!=null && Boolean.parseBoolean(endpoint.getDescriptor().getDebugging())) {
101                 dispatch = false;
102                 WebServiceTesterServlet.invoke(hreq, hresp,
103                                                endpoint.getDescriptor());
104             }
105         }
106
107         if (dispatch) {
108             EjbRuntimeEndpointInfo ejbEndpoint =
109                 WebServiceEjbEndpointRegistry.getRegistry().getEjbWebServiceEndpoint(requestUri, hreq.getMethod(), query);
110
111             if (ejbEndpoint != null) {
112                 /*
113                  * We can actually assert that ejbEndpoint is != null,
114                  * because this EjbWebServiceServlet would not have been
115                  * invoked otherwise
116                  */

117                 dispatchToEjbEndpoint(hreq, hresp, ejbEndpoint);
118             }
119         }
120     }
121
122
123     private void dispatchToEjbEndpoint(HttpServletRequest JavaDoc hreq,
124                                        HttpServletResponse JavaDoc hresp,
125                                        EjbRuntimeEndpointInfo ejbEndpoint) {
126
127         String JavaDoc scheme = hreq.getScheme();
128         String JavaDoc expectedScheme = ejbEndpoint.getEndpoint().isSecure() ?
129             "https" : "http";
130
131         if( !expectedScheme.equalsIgnoreCase(scheme) ) {
132             logger.log(Level.WARNING, "Invalid request scheme for Endpoint " +
133                        ejbEndpoint.getEndpoint().getEndpointName() + ". " +
134                        "Expected " + expectedScheme + " . Received " + scheme);
135             return;
136         }
137
138         Switch theSwitch = Switch.getSwitch();
139         Container container = ejbEndpoint.getContainer();
140         
141         boolean authenticated = false;
142         try {
143             // Set context class loader to application class loader
144
container.externalPreInvoke();
145
146            // compute realmName
147
String JavaDoc realmName = ejbEndpoint.getEndpoint().getRealm();
148             if (realmName == null) {
149                 Application app = ejbEndpoint.getEndpoint().getBundleDescriptor().getApplication();
150                 if (app != null) {
151                     realmName = app.getRealm();
152                 }
153             }
154             if (realmName == null) {
155                 // use the same logic as BasicAuthenticator
156
realmName = hreq.getServerName() + ":" + hreq.getServerPort();
157             }
158             
159             try {
160                 authenticated = doSecurity(hreq, ejbEndpoint, realmName);
161             } catch(Exception JavaDoc e) {
162                 sendAuthenticationEvents(false, hreq.getRequestURL().toString(), null);
163                 logger.log(Level.WARNING, "authentication failed for " +
164                            ejbEndpoint.getEndpoint().getEndpointName(),
165                            e);
166             }
167
168             if (auditManager.isAuditOn()){
169
170                 auditManager.ejbAsWebServiceInvocation(
171                     ejbEndpoint.getEndpoint().getEndpointName(),authenticated);
172             }
173
174
175
176             if (!authenticated) {
177                 hresp.setHeader("WWW-Authenticate",
178                         "Basic realm=\"" + realmName + "\"");
179                 hresp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
180                 return;
181             }
182             
183             // depending on the jaxrpc or jax-ws version, this will return the
184
// right dispatcher.
185
EjbMessageDispatcher msgDispatcher = ejbEndpoint.getMessageDispatcher();
186             msgDispatcher.invoke(hreq, hresp, ejbEndpoint);
187             
188         } catch(Throwable JavaDoc t) {
189             logger.log(Level.WARNING, "", t);
190         } finally {
191             if( authenticated ) {
192                 // remove any security context from the thread before returning
193
SecurityContext.setCurrent(null);
194             }
195             
196             // Restore context class loader
197
container.externalPostInvoke();
198         }
199         return;
200     }
201     
202     private boolean doSecurity(HttpServletRequest JavaDoc hreq,
203                                EjbRuntimeEndpointInfo epInfo,
204                                String JavaDoc realmName) throws Exception JavaDoc {
205
206         WebServiceEndpoint endpoint = epInfo.getEndpoint();
207         boolean authenticated = false;
208         
209         String JavaDoc method = hreq.getMethod();
210         if( method.equals("GET") || !endpoint.hasAuthMethod() ) {
211             return true;
212         }
213         
214         WebPrincipal webPrincipal = null;
215         String JavaDoc endpointName = endpoint.getEndpointName();
216         
217         if( endpoint.hasBasicAuth() ) {
218             String JavaDoc rawAuthInfo = hreq.getHeader(AUTHORIZATION_HEADER);
219             if (rawAuthInfo==null) {
220                 sendAuthenticationEvents(false, hreq.getRequestURL().toString(), null);
221                 return false;
222             }
223             
224             String JavaDoc[] usernamePassword =
225                     parseUsernameAndPassword(rawAuthInfo);
226             if( usernamePassword != null ) {
227                 webPrincipal = new WebPrincipal
228                         (usernamePassword[0], usernamePassword[1], SecurityContext.init());
229             } else {
230                 logger.log(Level.WARNING, "BASIC AUTH username/password " +
231                            "http header parsing error for " + endpointName);
232             }
233         } else {
234
235             X509Certificate JavaDoc certs[] = (X509Certificate JavaDoc[]) hreq.getAttribute(Globals.CERTIFICATES_ATTR);
236             if ((certs == null) || (certs.length < 1)) {
237                 certs = (X509Certificate JavaDoc[])
238                     hreq.getAttribute(Globals.SSL_CERTIFICATE_ATTR);
239             }
240
241             if( certs != null ) {
242                 webPrincipal = new WebPrincipal(certs, SecurityContext.init());
243             } else {
244                 logger.log(Level.WARNING, "CLIENT CERT authentication error for " + endpointName);
245             }
246
247         }
248
249         if (webPrincipal==null) {
250             sendAuthenticationEvents(false, hreq.getRequestURL().toString(), null);
251             return authenticated;
252         }
253         
254         RealmAdapter ra = new RealmAdapter(realmName);
255         authenticated = ra.authenticate(webPrincipal);
256         if( authenticated == false ) {
257             sendAuthenticationEvents(false, hreq.getRequestURL().toString(), webPrincipal);
258             logger.fine("authentication failed for " + endpointName);
259         }
260
261         sendAuthenticationEvents(true, hreq.getRequestURL().toString(), webPrincipal);
262         //Setting if userPrincipal in WSCtxt applies for JAXWS endpoints only
263
if(!(epInfo instanceof Ejb2RuntimeEndpointInfo)) {
264             WebServiceContextImpl ctxt = (WebServiceContextImpl)
265                 epInfo.prepareInvocation(false).getWebServiceContext();
266             ctxt.setUserPrincipal(webPrincipal);
267         }
268         return authenticated;
269     }
270
271     private String JavaDoc[] parseUsernameAndPassword(String JavaDoc rawAuthInfo) {
272
273         String JavaDoc[] usernamePassword = null;
274         if ( (rawAuthInfo != null) &&
275              (rawAuthInfo.startsWith("Basic ")) ) {
276             String JavaDoc authString = rawAuthInfo.substring(6).trim();
277             // Decode and parse the authorization credentials
278
String JavaDoc unencoded =
279                 new String JavaDoc(base64Helper.decode(authString.getBytes()));
280             int colon = unencoded.indexOf(':');
281             if (colon > 0) {
282                 usernamePassword = new String JavaDoc[2];
283                 usernamePassword[0] = unencoded.substring(0, colon).trim();
284                 usernamePassword[1] = unencoded.substring(colon + 1).trim();
285             }
286         }
287         return usernamePassword;
288     }
289
290     private void sendAuthenticationEvents(boolean success,
291             String JavaDoc url, WebPrincipal principal) {
292         
293         Endpoint endpoint = WebServiceEngineImpl.getInstance().getEndpoint(url);
294         if (endpoint==null) {
295             return;
296         }
297         
298         for (AuthenticationListener listener : WebServiceEngineImpl.getInstance().getAuthListeners()) {
299             if (success) {
300                 listener.authSucess(endpoint.getDescriptor().getBundleDescriptor(),
301                         endpoint, principal);
302             } else {
303                 listener.authFailure(endpoint.getDescriptor().getBundleDescriptor(),
304                         endpoint, principal);
305             }
306         }
307     }
308 }
309
Popular Tags