Genericized the protocol handler interface in preperation for SAML2.
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 5 Sep 2006 15:47:04 +0000 (15:47 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 5 Sep 2006 15:47:04 +0000 (15:47 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@2008 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/idp/IdPProtocolHandler.java
src/edu/internet2/middleware/shibboleth/idp/IdPResponder.java
src/edu/internet2/middleware/shibboleth/idp/RequestHandlingException.java [new file with mode: 0644]

index cae5c25..7a1a92a 100644 (file)
 
 package edu.internet2.middleware.shibboleth.idp;
 
-import java.io.IOException;
-
-import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.opensaml.SAMLException;
-import org.opensaml.SAMLRequest;
-import org.opensaml.SAMLResponse;
-
 /**
  * Defines the processing for an IdP-supported protocol. A particular <code>IdPProtocolHandler</code> implementation
  * is registered to process requests delivered from one or more URL locations. Core IdP functionality is delivered
@@ -41,16 +34,14 @@ public interface IdPProtocolHandler {
        public String getHandlerName();
 
        /**
-        * Runs the protocol-specific request processing.
+        * Runs the protocol-specific request processing. Responsible for updating the <code>HttpServletResponse</code>.
         * 
-        * @param samlRequest
-        *            the request that inititiated the transaction or null
-        * @param support
-        * @return a <code>SAMLResponse</code> object that should be delivered to the binding upon which the request was
-        *         received or null
+        * @throws RequestHandlingException
+        *             if the handler is unable to successfully respond with a successfull protocol exchange or a
+        *             protocol-defined error message
         */
-       public SAMLResponse processRequest(HttpServletRequest request, HttpServletResponse response,
-                       SAMLRequest samlRequest, IdPProtocolSupport support) throws SAMLException, IOException, ServletException;
+       public void processRequest(HttpServletRequest request, HttpServletResponse response, IdPProtocolSupport support)
+                       throws RequestHandlingException;
 
        /**
         * Returns the locations for which this handler should process requests.
index d4f39a1..5bf2270 100644 (file)
@@ -35,11 +35,6 @@ import javax.xml.parsers.ParserConfigurationException;
 import org.apache.log4j.Logger;
 import org.apache.log4j.MDC;
 import org.opensaml.Configuration;
-import org.opensaml.SAMLBinding;
-import org.opensaml.SAMLBindingFactory;
-import org.opensaml.SAMLException;
-import org.opensaml.SAMLRequest;
-import org.opensaml.SAMLResponse;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -61,8 +56,8 @@ import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationExcepti
 import edu.internet2.middleware.shibboleth.log.LoggingInitializer;
 
 /**
- * Primary entry point for requests to the SAML IdP. Listens on multiple endpoints, routes requests to the appropriate
- * IdP processing components, and delivers proper protocol responses.
+ * Primary entry point for requests to the Shibboleth IdP. Listens on multiple endpoints, routes requests to the
+ * appropriate IdP processing components, and delivers proper protocol responses.
  * 
  * @author Walter Hoehn
  */
@@ -72,7 +67,6 @@ public class IdPResponder extends HttpServlet {
        private static Logger transactionLog;
        private static Logger log;
        private static Random idgen = new Random();
-       private SAMLBinding binding;
 
        private IdPConfig configuration;
        private Map<String, IdPProtocolHandler> protocolHandlers = new HashMap<String, IdPProtocolHandler>();
@@ -81,16 +75,15 @@ public class IdPResponder extends HttpServlet {
        /*
         * @see javax.servlet.GenericServlet#init()
         */
+       @SuppressWarnings("unused")
        public void init(ServletConfig servletConfig) throws ServletException {
 
                super.init(servletConfig);
-               
+
                // Load OpenSAML2
                Configuration.init();
 
                try {
-                       binding = SAMLBindingFactory.getInstance(SAMLBinding.SOAP);
-
                        Document idPConfig = IdPConfigLoader.getIdPConfig(this.getServletContext());
 
                        // Initialize logging
@@ -239,9 +232,6 @@ public class IdPResponder extends HttpServlet {
                                log.fatal("The Identity Provider could not be initialized: " + ae);
                        }
                        throw new UnavailableException("Identity Provider failed to initialize.");
-               } catch (SAMLException se) {
-                       log.fatal("SAML SOAP binding could not be loaded: " + se);
-                       throw new UnavailableException("Identity Provider failed to initialize.");
                }
        }
 
@@ -251,24 +241,17 @@ public class IdPResponder extends HttpServlet {
         */
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
-               MDC.put("serviceId", "[IdP] " + idgen.nextInt());
-               MDC.put("remoteAddr", request.getRemoteAddr());
                log.debug("Received a request via GET for location (" + request.getRequestURL() + ").");
 
                try {
-                       IdPProtocolHandler activeHandler = lookupProtocolHandler(request);
-                       // Pass request to the appropriate handler
-                       log.info("Processing " + activeHandler.getHandlerName() + " request.");
-                       if (activeHandler.processRequest(request, response, null, protocolSupport) != null) {
-                               // This shouldn't happen unless somebody configures a protocol handler incorrectly
-                               log.error("Protocol Handler returned a SAML Response, but there is no binding to handle it.");
-                               throw new SAMLException(SAMLException.RESPONDER, "General error processing request.");
-                       }
-
-               } catch (SAMLException ex) {
-                       log.error(ex);
-                       displayBrowserError(request, response, ex);
-                       return;
+                       processRequest(request, response);
+
+               } catch (RequestHandlingException e) {
+                       log.error("Error while processing GET request: " + e);
+                       sendGenericGetError(request, response, e);
+               } finally {
+                       MDC.remove("serviceId");
+                       MDC.remove("remoteAddr");
                }
        }
 
@@ -278,42 +261,38 @@ public class IdPResponder extends HttpServlet {
         */
        public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
-               MDC.put("serviceId", "[IdP] " + idgen.nextInt());
-               MDC.put("remoteAddr", request.getRemoteAddr());
                log.debug("Received a request via POST for location (" + request.getRequestURL() + ").");
 
-               // Parse SOAP request and marshall SAML request object
-               SAMLRequest samlRequest = null;
                try {
-                       try {
-                               samlRequest = binding.receive(request, 1);
-                       } catch (SAMLException e) {
-                               log.fatal("Unable to parse request: " + e);
-                               throw new SAMLException("Invalid request data.");
-                       }
-
-                       // If we have DEBUG logging turned on, dump out the request to the log
-                       // This takes some processing, so only do it if we need to
-                       if (log.isDebugEnabled()) {
-                               log.debug("Dumping generated SAML Request:" + System.getProperty("line.separator")
-                                               + samlRequest.toString());
-                       }
+                       processRequest(request, response);
+
+               } catch (RequestHandlingException e) {
+                       log.error("Error while processing POST request: " + e);
+                       sendGenericPostError(response, e);
+               } finally {
+                       MDC.remove("serviceId");
+                       MDC.remove("remoteAddr");
+               }
+       }
 
-                       IdPProtocolHandler activeHandler = lookupProtocolHandler(request);
-                       // Pass request to the appropriate handler and respond
-                       log.info("Processing " + activeHandler.getHandlerName() + " request.");
+       /**
+        * Refers the request to the appropriate protocol handler
+        */
+       private void processRequest(HttpServletRequest request, HttpServletResponse response)
+                       throws RequestHandlingException {
 
-                       SAMLResponse samlResponse = activeHandler.processRequest(request, response, samlRequest, protocolSupport);
-                       binding.respond(response, samlResponse, null);
+               MDC.put("serviceId", "[IdP] " + idgen.nextInt());
+               MDC.put("remoteAddr", request.getRemoteAddr());
 
-               } catch (SAMLException e) {
-                       sendFailureToSAMLBinding(response, samlRequest, e);
-               }
+               IdPProtocolHandler activeHandler = lookupProtocolHandler(request);
+               // Pass request to the appropriate handler and respond
+               log.info("Processing " + activeHandler.getHandlerName() + " request.");
+               activeHandler.processRequest(request, response, protocolSupport);
        }
 
-       private IdPProtocolHandler lookupProtocolHandler(HttpServletRequest request) throws SAMLException {
+       /** Determine which protocol handler is active for this endpoint */
+       private IdPProtocolHandler lookupProtocolHandler(HttpServletRequest request) throws RequestHandlingException {
 
-               // Determine which protocol handler is active for this endpoint
                String requestURL = request.getRequestURL().toString();
                IdPProtocolHandler activeHandler = null;
 
@@ -329,11 +308,15 @@ public class IdPResponder extends HttpServlet {
 
                if (activeHandler == null) {
                        log.error("No protocol handler registered for location (" + request.getRequestURL() + ").");
-                       throw new SAMLException("Request submitted to an invalid location.");
+                       throw new RequestHandlingException("Request submitted to an invalid location.");
                }
                return activeHandler;
        }
 
+       /**
+        * Specifies a default set of IDPProtocolHandler configurations that should be used if none are specified in the IdP
+        * configuration.
+        */
        private NodeList getDefaultHandlers() throws ShibbolethConfigurationException {
 
                log.debug("Loading default protocol handler configuration.");
@@ -375,36 +358,24 @@ public class IdPResponder extends HttpServlet {
                }
        }
 
-       private void sendFailureToSAMLBinding(HttpServletResponse httpResponse, SAMLRequest samlRequest,
-                       SAMLException exception) throws ServletException {
+       /**
+        * Generic error response for GET requests.
+        */
+       private void sendGenericPostError(HttpServletResponse httpResponse, RequestHandlingException exception)
+                       throws ServletException {
 
-               log.error("Error while processing request: " + exception);
                try {
-                       SAMLResponse samlResponse = new SAMLResponse((samlRequest != null) ? samlRequest.getId() : null, null,
-                                       null, exception);
-                       if (log.isDebugEnabled()) {
-                               log.debug("Dumping generated SAML Error Response:" + System.getProperty("line.separator")
-                                               + samlResponse.toString());
-                       }
-                       binding.respond(httpResponse, samlResponse, null);
-                       log.debug("Returning SAML Error Response.");
-               } catch (SAMLException se) {
-                       try {
-                               binding.respond(httpResponse, null, exception);
-                       } catch (SAMLException e) {
-                               log.error("Caught exception while responding to requester: " + e.getMessage());
-                               try {
-                                       httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while responding.");
-                               } catch (IOException ee) {
-                                       log.fatal("Could not construct a SAML error response: " + ee);
-                                       throw new ServletException("Identity Provider response failure.");
-                               }
-                       }
-                       log.error("Identity Provider failed to make an error message: " + se);
+                       httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while responding.");
+               } catch (IOException ee) {
+                       log.fatal("Could not construct a SAML error response: " + ee);
+                       throw new ServletException("Identity Provider response failure.");
                }
        }
 
-       private static void displayBrowserError(HttpServletRequest req, HttpServletResponse res, Exception e)
+       /**
+        * Generic error response for GET requests.
+        */
+       private void sendGenericGetError(HttpServletRequest req, HttpServletResponse res, RequestHandlingException e)
                        throws ServletException, IOException {
 
                req.setAttribute("errorText", e.toString());
diff --git a/src/edu/internet2/middleware/shibboleth/idp/RequestHandlingException.java b/src/edu/internet2/middleware/shibboleth/idp/RequestHandlingException.java
new file mode 100644 (file)
index 0000000..8655e2c
--- /dev/null
@@ -0,0 +1,14 @@
+
+package edu.internet2.middleware.shibboleth.idp;
+
+/**
+ * Signals that an IdPProtocolHandler was unable to respond appropriately to a request.
+ */
+public class RequestHandlingException extends Exception {
+
+       RequestHandlingException(String message) {
+
+               super(message);
+       }
+
+}