List of usage examples for java.io UnsupportedEncodingException getClass
@HotSpotIntrinsicCandidate public final native Class<?> getClass();
From source file:be.fedict.eid.idp.sp.protocol.ws_federation.AuthenticationResponseProcessor.java
/** * Process the incoming WS-Federation response. * // w w w . j a v a 2 s .c om * @param recipient * recipient, should match SAML v2.0 assertions's * AudienceRestriction * @param context * optional expected context * @param requiresResponseSignature * do we expect a signature on the response or not, or * <code>null</code> if to be retrieved from the * {@link AuthenticationResponseService}. * @param request * the HTTP servlet request that holds the SAML2 response. * @return the {@link be.fedict.eid.idp.common.saml2.AuthenticationResponse} * @throws AuthenticationResponseProcessorException * case something went wrong */ public AuthenticationResponse process(String recipient, String context, Boolean requiresResponseSignature, HttpServletRequest request) throws AuthenticationResponseProcessorException { DateTime now = new DateTime(); SecretKey secretKey = null; PrivateKey privateKey = null; int maxOffset = 5; boolean expectAssertionSigned = null != requiresResponseSignature ? requiresResponseSignature : false; ValidationService validationService = null; if (null != this.service) { secretKey = this.service.getAttributeSecretKey(); privateKey = this.service.getAttributePrivateKey(); maxOffset = this.service.getMaximumTimeOffset(); expectAssertionSigned = this.service.requiresResponseSignature(); validationService = this.service.getValidationService(); } // force UTF8 encoding! try { request.setCharacterEncoding("UTF8"); } catch (UnsupportedEncodingException e) { throw new AuthenticationResponseProcessorException(e); } // check wa String wa = request.getParameter("wa"); if (null == wa) { throw new AuthenticationResponseProcessorException("Missing \"wa\" param."); } if (!wa.equals("wsignin1.0")) { throw new AuthenticationResponseProcessorException("Unexpected value for \"wa\" param."); } // validate optional ctx validateContext(context, request.getParameter("wctx")); // get wresult String wresult = request.getParameter("wresult"); LOG.debug("wresult=\"" + wresult + "\""); if (null == wresult) { throw new AuthenticationResponseProcessorException("Missing \"wresult\" param."); } Document responseDocument = Saml2Util.parseDocument(wresult); RequestSecurityTokenResponseCollection rstCollections = Saml2Util .unmarshall(responseDocument.getDocumentElement()); if (rstCollections.getRequestSecurityTokenResponses().size() != 1) { throw new AuthenticationResponseProcessorException("Expected exactly 1 RequestSecurityTokenResponse"); } RequestSecurityTokenResponse rstResponse = rstCollections.getRequestSecurityTokenResponses().get(0); // context validateContext(context, rstResponse.getContext()); // tokentype validateTokenType(rstResponse); // requesttype validateRequestType(rstResponse); // keytype validateKeyType(rstResponse); // validate security token Assertion assertion = validateSecurityToken(rstResponse); // validate assertion AuthenticationResponse authenticationResponse; try { authenticationResponse = Saml2Util.validateAssertion(assertion, now, maxOffset, recipient, recipient, null, secretKey, privateKey); } catch (AssertionValidationException e) { throw new AuthenticationResponseProcessorException(e); } // check if SP expects a signature and if there is one if (null == assertion.getSignature() && expectAssertionSigned) { throw new AuthenticationResponseProcessorException("Expected a signed assertion but was not so! "); } // validate assertion's signature if any if (null != assertion.getSignature()) { try { // fix for recent versions of Apache xmlsec assertion.getDOM().setIdAttribute("ID", true); List<X509Certificate> certificateChain = Saml2Util.validateSignature(assertion.getSignature()); if (null != validationService) { // have to reparse the document here NodeList assertionNodeList = Saml2Util.parseDocument(wresult) .getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Assertion"); LOG.debug("number of SAML2 assertions: " + assertionNodeList.getLength()); if (1 != assertionNodeList.getLength()) { throw new AuthenticationResponseProcessorException("missing SAML2 Assertion"); } Element assertionElement = (Element) assertionNodeList.item(0); DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setNamespaceAware(true); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document tokenDocument = documentBuilder.newDocument(); Node assertionTokenNode = tokenDocument.importNode(assertionElement, true); tokenDocument.appendChild(assertionTokenNode); String validationServiceLocation = validationService.getLocation(); String expectedAudience = validationService.getExpectedAudience(); SecurityTokenServiceClient securityTokenServiceClient = new SecurityTokenServiceClient( validationServiceLocation); securityTokenServiceClient.validateToken(tokenDocument.getDocumentElement(), expectedAudience); } if (null != this.service) { this.service.validateServiceCertificate(authenticationResponse.getAuthenticationPolicy(), certificateChain); } } catch (CertificateException e) { throw new AuthenticationResponseProcessorException(e); } catch (ValidationException e) { throw new AuthenticationResponseProcessorException(e); } catch (Exception e) { if ("javax.ejb.EJBException".equals(e.getClass().getName())) { Exception exception; try { Method getCausedByExceptionMethod = e.getClass().getMethod("getCausedByException", new Class[] {}); exception = (Exception) getCausedByExceptionMethod.invoke(e, new Object[] {}); } catch (Exception e2) { LOG.debug("error: " + e.getMessage(), e); throw new AuthenticationResponseProcessorException( "error retrieving the root cause: " + e2.getMessage()); } throw new AuthenticationResponseProcessorException("Validation exception: " + (null != exception ? exception.getMessage() : e.getMessage())); } throw new AuthenticationResponseProcessorException(e); } } return authenticationResponse; }
From source file:fedora.server.access.dissemination.DisseminationService.java
/** * <p>//from w w w .j ava 2s . c o m * Assembles a dissemination given an instance of <code> * DisseminationBindingInfo</code> * which has the dissemination-related information from the digital object * and its associated Service Deployment object. * </p> * * @param context * The current context. * @param PID * The persistent identifier of the digital object. * @param h_userParms * A hashtable of user-supplied method parameters. * @param dissBindInfoArray * The associated dissemination binding information. * @return A MIME-typed stream containing the result of the dissemination. * @throws ServerException * If unable to assemble the dissemination for any reason. */ public MIMETypedStream assembleDissemination(Context context, String PID, Hashtable h_userParms, DisseminationBindingInfo[] dissBindInfoArray, String deploymentPID, ServiceDeploymentReader bmReader, String methodName) throws ServerException { LOG.debug("Started assembling dissemination"); String dissURL = null; String protocolType = null; DisseminationBindingInfo dissBindInfo = null; MIMETypedStream dissemination = null; long initStartTime = new Date().getTime(); boolean isRedirect = false; if (LOG.isDebugEnabled()) { printBindingInfo(dissBindInfoArray); } if (dissBindInfoArray != null && dissBindInfoArray.length > 0) { String replaceString = null; int numElements = dissBindInfoArray.length; // Get row(s) of binding info and perform string substitution // on DSBindingKey and method parameter values in WSDL // Note: In case where more than one datastream matches the // DSBindingKey or there are multiple DSBindingKeys for the // method, multiple rows will be present; otherwise there is only // a single row. for (int i = 0; i < dissBindInfoArray.length; i++) { ((Authorization) s_server.getModule("fedora.server.security.Authorization")) .enforce_Internal_DSState(context, dissBindInfoArray[i].dsID, dissBindInfoArray[i].dsState); dissBindInfo = dissBindInfoArray[i]; // Before doing anything, check whether we can replace any // placeholders in the datastream url with parameter values from // the request. This supports the special case where a // datastream's URL is dependent on user parameters, such // as when the datastream is actually a dissemination that // takes parameters. if (dissBindInfo.dsLocation != null && (dissBindInfo.dsLocation.startsWith("http://") || dissBindInfo.dsLocation.startsWith("https://"))) { String[] parts = dissBindInfo.dsLocation.split("=\\("); // regex for =( if (parts.length > 1) { StringBuffer replaced = new StringBuffer(); replaced.append(parts[0]); for (int x = 1; x < parts.length; x++) { replaced.append('='); int rightParenPos = parts[x].indexOf(")"); if (rightParenPos != -1 && rightParenPos > 0) { String key = parts[x].substring(0, rightParenPos); String val = (String) h_userParms.get(key); if (val != null) { // We have a match... so insert the urlencoded value. try { replaced.append(URLEncoder.encode(val, "UTF-8")); } catch (UnsupportedEncodingException uee) { // won't happen: java always supports UTF-8 } if (rightParenPos < parts[x].length()) { replaced.append(parts[x].substring(rightParenPos + 1)); } } else { replaced.append('('); replaced.append(parts[x]); } } else { replaced.append('('); replaced.append(parts[x]); } } dissBindInfo.dsLocation = replaced.toString(); } } // Match DSBindingKey pattern in WSDL which is a string of the form: // (DSBindingKey). Rows in DisseminationBindingInfo are sorted // alphabetically on binding key. String bindingKeyPattern = "\\(" + dissBindInfo.DSBindKey + "\\)"; if (i == 0) { // If addressLocation has a value of "LOCAL", this indicates // the associated operationLocation requires no addressLocation. // i.e., the operationLocation contains all information necessary // to perform the dissemination request. This is a special case // used when the web services are generally mechanisms like cgi-scripts, // java servlets, and simple HTTP GETs. Using the value of LOCAL // in the address location also enables one to have different methods // serviced by different hosts. In true web services like SOAP, the // addressLocation specifies the host name of the service and all // methods are served from that single host location. if (dissBindInfo.AddressLocation.equalsIgnoreCase(LOCAL_ADDRESS_LOCATION)) { dissURL = dissBindInfo.OperationLocation; } else { dissURL = dissBindInfo.AddressLocation + dissBindInfo.OperationLocation; } protocolType = dissBindInfo.ProtocolType; } // Assess beSecurity for backend service and for datastreams that may be parameters for the // backend service. // // dsMediatedCallbackHost - when dsMediation is in effect, all M, X, and E type datastreams // are encoded as callbacks to the Fedora server to obtain the // datastream's contents. dsMediatedCallbackHost contains protocol, // host, and port used for this type of backendservice-to-fedora callback. // The specifics of protocol, host, and port are obtained from the // beSecurity configuration file. // dsMediatedServletPath - when dsMediation is in effect, all M, X, and E type datastreams // are encoded as callbacks to the Fedora server to obtain the // datastream's contents. dsMediatedServletPath contains the servlet // path info for this type of backendservice-to-fedora callback. // The specifics of servlet path are obtained from the beSecurity configuration // file and determines whether the backedservice-to-fedora callback // will use authentication or not. // callbackRole - contains the role of the backend service (the deploymentPID of the service). String callbackRole = deploymentPID; Hashtable beHash = m_beSS.getSecuritySpec(callbackRole, methodName); boolean callbackBasicAuth = new Boolean((String) beHash.get("callbackBasicAuth")).booleanValue(); boolean callbackSSL = new Boolean((String) beHash.get("callbackSSL")).booleanValue(); String dsMediatedServletPath = null; if (callbackBasicAuth) { dsMediatedServletPath = "/fedora/getDSAuthenticated?id="; } else { dsMediatedServletPath = "/fedora/getDS?id="; } String dsMediatedCallbackHost = null; if (callbackSSL) { dsMediatedCallbackHost = "https://" + fedoraServerHost + ":" + fedoraServerRedirectPort; } else { dsMediatedCallbackHost = "http://" + fedoraServerHost + ":" + fedoraServerPort; } String datastreamResolverServletURL = dsMediatedCallbackHost + dsMediatedServletPath; if (LOG.isDebugEnabled()) { LOG.debug("******************Checking backend service dsLocation: " + dissBindInfo.dsLocation); LOG.debug("******************Checking backend service dsControlGroupType: " + dissBindInfo.dsControlGroupType); LOG.debug("******************Checking backend service callbackBasicAuth: " + callbackBasicAuth); LOG.debug("******************Checking backend service callbackSSL: " + callbackSSL); LOG.debug("******************Checking backend service callbackRole: " + callbackRole); LOG.debug("******************DatastreamResolverServletURL: " + datastreamResolverServletURL); } String currentKey = dissBindInfo.DSBindKey; String nextKey = ""; if (i != numElements - 1) { // Except for last row, get the value of the next binding key // to compare with the value of the current binding key. nextKey = dissBindInfoArray[i + 1].DSBindKey; } LOG.debug("currentKey: '" + currentKey + "', nextKey: '" + nextKey + "'"); // In most cases, there is only a single datastream that matches a // given DSBindingKey so the substitution process is to just replace // the occurence of (BINDING_KEY) with the value of the datastream // location. However, when multiple datastreams match the same // DSBindingKey, the occurrence of (BINDING_KEY) is replaced with the // value of the datastream location and the value +(BINDING_KEY) is // appended so that subsequent datastreams matching the binding key // will be substituted. The end result is that the binding key will // be replaced by a series of datastream locations separated by a // plus(+) sign. For example, in the case where 3 datastreams match // the binding key for PHOTO: // // file=(PHOTO) becomes // file=dslocation1+dslocation2+dslocation3 // // It is the responsibility of the Service Deployment to know how to // handle an input parameter with multiple datastream locations. // // In the case of a method containing multiple binding keys, // substitutions are performed on each binding key. For example, in // the case where there are 2 binding keys named PHOTO and WATERMARK // where each matches a single datastream: // // image=(PHOTO)&watermark=(WATERMARK) becomes // image=dslocation1&watermark=dslocation2 // // In the case with mutliple binding keys and multiple datastreams, // the substitution might appear like the following: // // image=(PHOTO)&watermark=(WATERMARK) becomes // image=dslocation1+dslocation2&watermark=dslocation3 if (nextKey.equalsIgnoreCase(currentKey) & i != numElements) { // Case where binding keys are equal which means that multiple // datastreams matched the same binding key. if (doDatastreamMediation && !dissBindInfo.dsControlGroupType.equalsIgnoreCase("R")) { // Use Datastream Mediation (except for redirected datastreams). replaceString = datastreamResolverServletURL + registerDatastreamLocation(dissBindInfo.dsLocation, dissBindInfo.dsControlGroupType, callbackRole, methodName) + "+(" + dissBindInfo.DSBindKey + ")"; } else { // Bypass Datastream Mediation. if (dissBindInfo.dsControlGroupType.equalsIgnoreCase("M") || dissBindInfo.dsControlGroupType.equalsIgnoreCase("X")) { // Use the Default Disseminator syntax to resolve the internal // datastream location for Managed and XML datastreams. replaceString = resolveInternalDSLocation(context, dissBindInfo.dsLocation, PID, dsMediatedCallbackHost) + "+(" + dissBindInfo.DSBindKey + ")"; ; } else { replaceString = dissBindInfo.dsLocation + "+(" + dissBindInfo.DSBindKey + ")"; } if (dissBindInfo.dsControlGroupType.equalsIgnoreCase("R") && dissBindInfo.AddressLocation.equals(LOCAL_ADDRESS_LOCATION)) { isRedirect = true; } } } else { // Case where there are one or more binding keys. if (doDatastreamMediation && !dissBindInfo.dsControlGroupType.equalsIgnoreCase("R")) { // Use Datastream Mediation (except for Redirected datastreams) replaceString = datastreamResolverServletURL + registerDatastreamLocation( dissBindInfo.dsLocation, dissBindInfo.dsControlGroupType, callbackRole, methodName); //this is generic, should be made specific per service } else { // Bypass Datastream Mediation. if (dissBindInfo.dsControlGroupType.equalsIgnoreCase("M") || dissBindInfo.dsControlGroupType.equalsIgnoreCase("X")) { // Use the Default Disseminator syntax to resolve the internal // datastream location for Managed and XML datastreams. replaceString = resolveInternalDSLocation(context, dissBindInfo.dsLocation, PID, dsMediatedCallbackHost); } else { replaceString = dissBindInfo.dsLocation; } if (dissBindInfo.dsControlGroupType.equalsIgnoreCase("R") && dissBindInfo.AddressLocation.equals(LOCAL_ADDRESS_LOCATION)) { isRedirect = true; } } } try { // If the operationLocation contains datastreamInputParms // URLEncode each parameter before substitution. Otherwise, the // operationLocation has no parameters (i.e., it is a simple URL ) // so bypass URLencoding. if (dissURL.indexOf("=(") != -1) { dissURL = substituteString(dissURL, bindingKeyPattern, URLEncoder.encode(replaceString, "UTF-8")); } else { dissURL = substituteString(dissURL, bindingKeyPattern, replaceString); } } catch (UnsupportedEncodingException uee) { String message = "[DisseminationService] An error occured. The error " + "was \"" + uee.getClass().getName() + "\" . The Reason was \"" + uee.getMessage() + "\" . String value: " + replaceString + " . "; LOG.error(message); throw new GeneralException(message); } LOG.debug("Replaced dissURL: " + dissURL.toString() + " DissBindingInfo index: " + i); } DeploymentDSBindSpec dsBindSpec = bmReader.getServiceDSInputSpec(null); DeploymentDSBindRule rules[] = dsBindSpec.dsBindRules; for (DeploymentDSBindRule element : rules) { String rulePattern = "(" + element.bindingKeyName + ")"; if (dissURL.indexOf(rulePattern) != -1) { throw new DisseminationException(null, "Data Object " + PID + " missing required datastream: " + element.bindingKeyName, null, null, null); } } // Substitute method parameter values in dissemination URL Enumeration e = h_userParms.keys(); while (e.hasMoreElements()) { String name = null; String value = null; try { name = URLEncoder.encode((String) e.nextElement(), "UTF-8"); value = URLEncoder.encode((String) h_userParms.get(name), "UTF-8"); } catch (UnsupportedEncodingException uee) { String message = "[DisseminationService] An error occured. The error " + "was \"" + uee.getClass().getName() + "\" . The Reason was \"" + uee.getMessage() + "\" . Parameter name: " + name + " . " + "Parameter value: " + value + " ."; LOG.error(message); throw new GeneralException(message); } String pattern = "\\(" + name + "\\)"; dissURL = substituteString(dissURL, pattern, value); LOG.debug("User parm substituted in URL: " + dissURL); } // FIXME Need a more elegant means of handling optional userInputParm // method parameters that are not supplied by the invoking client; // for now, any optional parms that were not supplied are removed from // the outgoing URL. This works because parms are validated in // DefaultAccess to insure all required parms are present and all parm // names match parm names defined for the specific method. The only // unsubstituted parms left in the operationLocation string at this point // are those for optional parameters that the client omitted in the // initial request so they can safely be removed from the outgoing // dissemination URL. This step is only needed when optional parameters // are not supplied by the client. if (dissURL.indexOf("(") != -1) { dissURL = stripParms(dissURL); LOG.debug("Non-supplied optional userInputParm values removed " + "from URL: " + dissURL); } if (dissURL.indexOf("(") != -1) { String datastreamName = dissURL.substring(dissURL.indexOf("(") + 1, dissURL.indexOf(")")); throw new DisseminationException(null, "Data Object " + PID + " missing required datastream: " + datastreamName, null, null, null); } // Resolve content referenced by dissemination result. LOG.debug("ProtocolType: " + protocolType); if (protocolType.equalsIgnoreCase("http")) { if (isRedirect) { // The dsControlGroupType of Redirect("R") is a special control type // used primarily for streaming media. Datastreams of this type are // not mediated (proxied by Fedora) and their physical dsLocation is // simply redirected back to the client. Therefore, the contents // of the MIMETypedStream returned for dissemination requests will // contain the raw URL of the dsLocation and will be assigned a // special fedora-specific MIME type to identify the stream as // a MIMETypedStream whose contents contain a URL to which the client // should be redirected. InputStream is = null; try { is = new ByteArrayInputStream(dissURL.getBytes("UTF-8")); } catch (UnsupportedEncodingException uee) { String message = "[DisseminationService] An error has occurred. " + "The error was a \"" + uee.getClass().getName() + "\" . The " + "Reason was \"" + uee.getMessage() + "\" . String value: " + dissURL + " . "; LOG.error(message); throw new GeneralException(message); } LOG.debug("Finished assembling dissemination"); dissemination = new MIMETypedStream("application/fedora-redirect", is, null); } else { // For all non-redirected disseminations, Fedora captures and returns // the MIMETypedStream resulting from the dissemination request. //ExternalContentManager externalContentManager = (ExternalContentManager) // s_server.getModule("fedora.server.storage.ExternalContentManager"); LOG.debug("Finished assembling dissemination"); LOG.debug("URL: " + dissURL); // See if backend service reference is to fedora server itself or an external location. // We must examine URL to see if this is referencing a remote backend service or is // simply a callback to the fedora server. If the reference is remote, then use // the role of backend service deployment PID. If the referenc is to the fedora server, // use the special role of "fedoraInternalCall-1" to denote that the callback will come from the // fedora server itself. String beServiceRole = null; if (ServerUtility.isURLFedoraServer(dissURL)) { beServiceRole = BackendPolicies.FEDORA_INTERNAL_CALL; } else { beServiceRole = deploymentPID; } // Get basicAuth and SSL info about the backend service and use this info to configure the // "call" to the backend service. Hashtable beHash = m_beSS.getSecuritySpec(beServiceRole, methodName); boolean beServiceCallSSL = new Boolean((String) beHash.get("callSSL")).booleanValue(); String beServiceCallUsername = ""; String beServiceCallPassword = ""; boolean beServiceCallBasicAuth = new Boolean((String) beHash.get("callBasicAuth")) .booleanValue(); if (beServiceCallBasicAuth) { beServiceCallUsername = (String) beHash.get("callUsername"); beServiceCallPassword = (String) beHash.get("callPassword"); } /* * //fixup: if * (BackendPolicies.FEDORA_INTERNAL_CALL.equals(beServiceRole)) { * if (beServiceCallSSL) { if (dissURL.startsWith("http:")) { * dissURL = dissURL.replaceFirst("http:", "https:"); } if * (dissURL.indexOf(":"+fedoraServerPort+"/") >= 0) { * dissURL = dissURL.replaceFirst(":"+fedoraServerPort+"/", * ":"+fedoraServerRedirectPort+"/"); } } else { if * (dissURL.startsWith("https:")) { dissURL = * dissURL.replaceFirst("https:", "http:"); } if * (dissURL.indexOf(":"+fedoraServerRedirectPort+"/") >= 0) { * dissURL = * dissURL.replaceFirst(":"+fedoraServerRedirectPort+"/", * ":"+fedoraServerPort+"/"); } } if * (beServiceCallBasicAuth) { if (dissURL.indexOf("getDS?") >= * 0) { dissURL = dissURL.replaceFirst("getDS\\?", * "getDSAuthenticated\\?"); } } else { if * (dissURL.indexOf("getDSAuthenticated?") >= 0) { dissURL = * dissURL.replaceFirst("getDSAuthenticated\\?", * "getDS\\?"); } } } */ if (LOG.isDebugEnabled()) { LOG.debug("******************getDisseminationContent beServiceRole: " + beServiceRole); LOG.debug("******************getDisseminationContent beServiceCallBasicAuth: " + beServiceCallBasicAuth); LOG.debug( "******************getDisseminationContent beServiceCallSSL: " + beServiceCallSSL); LOG.debug("******************getDisseminationContent beServiceCallUsername: " + beServiceCallUsername); LOG.debug("******************getDisseminationContent beServiceCallPassword: " + beServiceCallPassword); LOG.debug("******************getDisseminationContent dissURL: " + dissURL); } // Dispatch backend service URL request authenticating as necessary based on beSecurity configuration dissemination = getDisseminationContent(dissURL, context, beServiceCallUsername, beServiceCallPassword); } } else if (protocolType.equalsIgnoreCase("soap")) { // FIXME!! future handling of soap bindings. String message = "[DisseminationService] Protocol type: " + protocolType + "NOT yet implemented"; LOG.error(message); throw new DisseminationException(message); } else { String message = "[DisseminationService] Protocol type: " + protocolType + "NOT supported."; LOG.error(message); throw new DisseminationException(message); } } else { // DisseminationBindingInfo was empty so there was no information // provided to construct a dissemination. String message = "[DisseminationService] Dissemination Binding " + "Info contained no data"; LOG.error(message); throw new DisseminationBindingInfoNotFoundException(message); } return dissemination; }