public boolean checkCorsPreflight(Request request, Response response) { log.finer("checkCorsPreflight " + request.getRequestURI()); if (!request.getMethod().equalsIgnoreCase("OPTIONS")) { log.finer("checkCorsPreflight: not options "); return false; } if (request.getHeader("Origin") == null) { log.finer("checkCorsPreflight: no origin header"); return false; } log.finer("Preflight request returning"); response.setStatus(HttpServletResponse.SC_OK); String origin = request.getHeader("Origin"); response.setHeader("Access-Control-Allow-Origin", origin); response.setHeader("Access-Control-Allow-Credentials", "true"); String requestMethods = request.getHeader("Access-Control-Request-Method"); if (requestMethods != null) { if (deployment.getCorsAllowedMethods() != null) { requestMethods = deployment.getCorsAllowedMethods(); } response.setHeader("Access-Control-Allow-Methods", requestMethods); } String allowHeaders = request.getHeader("Access-Control-Request-Headers"); if (allowHeaders != null) { if (deployment.getCorsAllowedHeaders() != null) { allowHeaders = deployment.getCorsAllowedHeaders(); } response.setHeader("Access-Control-Allow-Headers", allowHeaders); } if (deployment.getCorsMaxAge() > -1) { response.setHeader("Access-Control-Max-Age", Integer.toString(deployment.getCorsMaxAge())); } return true; }
@Test public final void testRequestUrlIgnorePatternIsUsedIfPrimaryMemcachedNodeIsOperational() throws IOException, ServletException { when(_memcachedNodesManager.isNodeAvailable(PRIMARY_NODE_IDENTIFIER)).thenReturn(true); when(_request.getRequestURI()).thenReturn("/pixel.gif"); _sessionTrackerValve.invoke(_request, _response); verify(_request).setNote(REQUEST_IGNORED, Boolean.TRUE); }
@Test public final void testRequestFinishedShouldBeInvokedForIgnoredResources() throws IOException, ServletException { when(_request.getRequestedSessionId()).thenReturn("foo"); when(_request.getRequestURI()).thenReturn("/pixel.gif"); _sessionTrackerValve.invoke(_request, _response); verify(_service).requestFinished(eq("foo"), anyString()); }
/** * Handle the HTTP status code (and corresponding message) generated while processing the * specified Request to produce the specified Response. Any exceptions that occur during * generation of the error report are logged and swallowed. * * @param request The request being processed * @param response The response being generated */ private void status(Request request, Response response) { int statusCode = response.getStatus(); // Handle a custom error page for this status code Context context = request.getContext(); if (context == null) return; /* Only look for error pages when isError() is set. * isError() is set when response.sendError() is invoked. This * allows custom error pages without relying on default from * web.xml. */ if (!response.isError()) return; ErrorPage errorPage = context.findErrorPage(statusCode); if (errorPage == null) { // Look for a default error page errorPage = context.findErrorPage(0); } if (errorPage != null && response.setErrorReported()) { response.setAppCommitted(false); request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, Integer.valueOf(statusCode)); String message = response.getMessage(); if (message == null) message = ""; request.setAttribute(RequestDispatcher.ERROR_MESSAGE, message); request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, errorPage.getLocation()); request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ERROR); Wrapper wrapper = request.getWrapper(); if (wrapper != null) request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, wrapper.getName()); request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI()); if (custom(request, response, errorPage)) { try { response.finishResponse(); } catch (ClientAbortException e) { // Ignore } catch (IOException e) { container.getLogger().warn("Exception Processing " + errorPage, e); } } } }
/** * /** When we do GET call for WSDL/WADL, we do not want to authenticate/throttle the request. * * <p>TODO check logic * * @param request * @param response * @param compositeValve * @param context */ private void handleWSDLGetRequest( Request request, Response response, CompositeValve compositeValve, String context) { if (request.getMethod().equals(Constants.Configuration.HTTP_METHOD_GET)) { // TODO:Need to get these paths from a config file. if (request.getRequestURI().matches(context + "/[^/]*/services")) { getNext().invoke(request, response, compositeValve); return; } Enumeration<String> params = request.getParameterNames(); String paramName = null; while (params.hasMoreElements()) { paramName = params.nextElement(); if (paramName.endsWith("wsdl") || paramName.endsWith("wadl")) { getNext().invoke(request, response, compositeValve); return; } } } }
@BeforeMethod public void setUp() throws Exception { _service = mock(MemcachedSessionService.class); _request = mock(Request.class); _response = mock(Response.class); final Context _contextContainer = mock(Context.class); final Host _hostContainer = mock(Host.class); final SessionManager _manager = mock(SessionManager.class); when(_service.getManager()).thenReturn(_manager); when(_manager.getContainer()).thenReturn(_contextContainer); when(_contextContainer.getParent()).thenReturn(_hostContainer); when(_contextContainer.getPath()).thenReturn("/"); _sessionTrackerValve = createSessionTrackerValve(); _nextValve = mock(Valve.class); _sessionTrackerValve.setNext(_nextValve); _sessionTrackerValve.setContainer(_hostContainer); _memcachedNodesManager = mock(MemcachedNodesManager.class); _sessionIdFormat = mock(SessionIdFormat.class); when(_request.getRequestURI()).thenReturn("/someRequest"); when(_request.getMethod()).thenReturn("GET"); when(_request.getQueryString()).thenReturn(null); when(_request.getContext()).thenReturn(_contextContainer); when(_request.getNote(eq(RequestTrackingHostValve.REQUEST_PROCESSED))).thenReturn(Boolean.TRUE); when(_request.getNote(eq(RequestTrackingHostValve.SESSION_ID_CHANGED))) .thenReturn(Boolean.FALSE); when(_sessionIdFormat.extractMemcachedId(anyString())).thenReturn(PRIMARY_NODE_IDENTIFIER); when(_service.getMemcachedNodesManager()).thenReturn(_memcachedNodesManager); when(_memcachedNodesManager.isNodeAvailable(PRIMARY_NODE_IDENTIFIER)) .thenReturn(IS_PRIMARY_MEMCACHED_NODE_OPERATIONAL); when(_memcachedNodesManager.getSessionIdFormat()).thenReturn(_sessionIdFormat); }
/** * Log the interesting request parameters, invoke the next Valve in the sequence, and log the * interesting response parameters. * * @param request The servlet request to be processed * @param response The servlet response to be created * @exception IOException if an input/output error occurs * @exception ServletException if a servlet error occurs */ public void invoke(Request request, Response response) throws IOException, ServletException { Log log = container.getLogger(); // Log pre-service information log.info("REQUEST URI =" + request.getRequestURI()); log.info(" authType=" + request.getAuthType()); log.info(" characterEncoding=" + request.getCharacterEncoding()); log.info(" contentLength=" + request.getContentLength()); log.info(" contentType=" + request.getContentType()); log.info(" contextPath=" + request.getContextPath()); Cookie cookies[] = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) log.info(" cookie=" + cookies[i].getName() + "=" + cookies[i].getValue()); } Enumeration hnames = request.getHeaderNames(); while (hnames.hasMoreElements()) { String hname = (String) hnames.nextElement(); Enumeration hvalues = request.getHeaders(hname); while (hvalues.hasMoreElements()) { String hvalue = (String) hvalues.nextElement(); log.info(" header=" + hname + "=" + hvalue); } } log.info(" locale=" + request.getLocale()); log.info(" method=" + request.getMethod()); Enumeration pnames = request.getParameterNames(); while (pnames.hasMoreElements()) { String pname = (String) pnames.nextElement(); String pvalues[] = request.getParameterValues(pname); StringBuffer result = new StringBuffer(pname); result.append('='); for (int i = 0; i < pvalues.length; i++) { if (i > 0) result.append(", "); result.append(pvalues[i]); } log.info(" parameter=" + result.toString()); } log.info(" pathInfo=" + request.getPathInfo()); log.info(" protocol=" + request.getProtocol()); log.info(" queryString=" + request.getQueryString()); log.info(" remoteAddr=" + request.getRemoteAddr()); log.info(" remoteHost=" + request.getRemoteHost()); log.info(" remoteUser="******"requestedSessionId=" + request.getRequestedSessionId()); log.info(" scheme=" + request.getScheme()); log.info(" serverName=" + request.getServerName()); log.info(" serverPort=" + request.getServerPort()); log.info(" servletPath=" + request.getServletPath()); log.info(" isSecure=" + request.isSecure()); log.info("---------------------------------------------------------------"); // Perform the request getNext().invoke(request, response); // Log post-service information log.info("---------------------------------------------------------------"); log.info(" authType=" + request.getAuthType()); log.info(" contentLength=" + response.getContentLength()); log.info(" contentType=" + response.getContentType()); Cookie rcookies[] = response.getCookies(); for (int i = 0; i < rcookies.length; i++) { log.info( " cookie=" + rcookies[i].getName() + "=" + rcookies[i].getValue() + "; domain=" + rcookies[i].getDomain() + "; path=" + rcookies[i].getPath()); } String rhnames[] = response.getHeaderNames(); for (int i = 0; i < rhnames.length; i++) { String rhvalues[] = response.getHeaderValues(rhnames[i]); for (int j = 0; j < rhvalues.length; j++) log.info(" header=" + rhnames[i] + "=" + rhvalues[j]); } log.info(" message=" + response.getMessage()); log.info(" remoteUser="******" status=" + response.getStatus()); log.info("==============================================================="); }
public void invoke(Request request, Response response, CompositeValve compositeValve) { if (authenticator == null) { authenticator = new APITokenAuthenticator(); } String context = request.getContextPath(); if (context == null || context.equals("")) { // Invoke next valve in pipe. getNext().invoke(request, response, compositeValve); return; } // todo remove version from context - special case for apps // context = stripVersionfromContext(context); boolean contextExist; Boolean contextValueInCache = null; if (APIUtil.getAPIContextCache().get(context) != null) { contextValueInCache = Boolean.parseBoolean(APIUtil.getAPIContextCache().get(context).toString()); } if (contextValueInCache != null) { contextExist = contextValueInCache; } else { contextExist = ApiMgtDAO.isContextExist(context); APIUtil.getAPIContextCache().put(context, contextExist); } if (!contextExist) { getNext().invoke(request, response, compositeValve); return; } handleWSDLGetRequest(request, response, compositeValve, context); String dispatcherPath = null; boolean forwardingRequired = false; long requestTime = System.currentTimeMillis(); APIManagerInterceptorOps interceptorOps = new APIManagerInterceptorOps(); UsageStatConfiguration statConfiguration = new UsageStatConfiguration(); if (contextExist) { // Use embedded API Management if (log.isDebugEnabled()) { log.debug("API Manager Interceptor Valve Got invoked!!"); } String bearerToken = request.getHeader(APIConstants.OperationParameter.AUTH_PARAM_NAME); String accessToken = null; /* Authenticate*/ try { if (bearerToken != null) { accessToken = APIManagetInterceptorUtils.getBearerToken(bearerToken); } else { // There can be some API published with None Auth Type /* * throw new * APIFaultException(APIConstants.KeyValidationStatus * .API_AUTH_INVALID_CREDENTIALS, * "Invalid format for Authorization header. Expected 'Bearer <token>'" * ); */ } String apiVersion = APIManagetInterceptorUtils.getAPIVersion(request); dispatcherPath = apiVersion; // todo get proper version // handling version for web-application API mgmt if (!APIManagerInterceptorConstant.DEFAULT_API_VERSION.equals(apiVersion) || "".equals(apiVersion)) { apiVersion = APIManagerInterceptorConstant.DEFAULT_API_VERSION; } else { forwardingRequired = true; } String domain = request.getHeader(APITokenValidator.getAPIManagerClientDomainHeader()); String authLevel = authenticator.getResourceAuthenticationScheme( context, apiVersion, request.getRequestURI(), request.getMethod()); if (authLevel.equals(APIConstants.NO_MATCHING_AUTH_SCHEME)) { APIManagetInterceptorUtils.handleNoMatchAuthSchemeCallForRestService( response, request.getMethod(), request.getRequestURI(), apiVersion, context); return; } else { interceptorOps.doAuthenticate( context, APIConstants.DEFAULT_VERSION_PREFIX + apiVersion, accessToken, authLevel, domain); } } catch (APIManagementException e) { // ignore } catch (APIFaultException e) { /* If !isAuthorized APIFaultException is thrown*/ APIManagetInterceptorUtils.handleAPIFaultForRestService( e, APIManagerErrorConstants.API_SECURITY_NS, APIManagerErrorConstants.API_SECURITY_NS_PREFIX, response); return; } /* Throttle*/ try { interceptorOps.doThrottle(request, accessToken); } catch (APIFaultException e) { APIManagetInterceptorUtils.handleAPIFaultForRestService( e, APIManagerErrorConstants.API_THROTTLE_NS, APIManagerErrorConstants.API_THROTTLE_NS_PREFIX, response); return; } /* Publish Statistic if enabled*/ if (statConfiguration.isStatsPublishingEnabled()) { try { interceptorOps.publishStatistics(request, requestTime, false); } catch (APIManagementException e) { log.error("Error occurred when publishing stats", e); } } } if (forwardingRequired) { try { request .getRequestDispatcher( request.getContextPath() + "/services/customers/customerservice/customers/123") .forward(request, response); // response.sendRedirect(request.getContextPath() + // "/services/customers/customerservice/customers/123"); // return; } catch (ServletException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } // Invoke next valve in pipe. getNext().invoke(request, response, compositeValve); // Handle Responses if (contextExist && statConfiguration.isStatsPublishingEnabled()) { try { interceptorOps.publishStatistics(request, requestTime, true); } catch (APIManagementException e) { log.error("Error occurred when publishing stats", e); } } }
/** * Handle the specified Throwable encountered while processing the specified Request to produce * the specified Response. Any exceptions that occur during generation of the exception report are * logged and swallowed. * * @param request The request being processed * @param response The response being generated * @param throwable The exception that occurred (which possibly wraps a root cause exception */ protected void throwable(Request request, Response response, Throwable throwable) { Context context = request.getContext(); if (context == null) return; Throwable realError = throwable; if (realError instanceof ServletException) { realError = ((ServletException) realError).getRootCause(); if (realError == null) { realError = throwable; } } // If this is an aborted request from a client just log it and return if (realError instanceof ClientAbortException) { if (log.isDebugEnabled()) { log.debug(sm.getString("standardHost.clientAbort", realError.getCause().getMessage())); } return; } ErrorPage errorPage = findErrorPage(context, throwable); if ((errorPage == null) && (realError != throwable)) { errorPage = findErrorPage(context, realError); } if (errorPage != null) { if (response.setErrorReported()) { response.setAppCommitted(false); request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, errorPage.getLocation()); request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ERROR); request.setAttribute( RequestDispatcher.ERROR_STATUS_CODE, new Integer(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)); request.setAttribute(RequestDispatcher.ERROR_MESSAGE, throwable.getMessage()); request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, realError); Wrapper wrapper = request.getWrapper(); if (wrapper != null) request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, wrapper.getName()); request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI()); request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE, realError.getClass()); if (custom(request, response, errorPage)) { try { response.finishResponse(); } catch (IOException e) { container.getLogger().warn("Exception Processing " + errorPage, e); } } } } else { // A custom error-page has not been defined for the exception // that was thrown during request processing. Check if an // error-page for error code 500 was specified and if so, // send that page back as the response. response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // The response is an error response.setError(); status(request, response); } }
/** * Select the appropriate child Context to process this request, based on the specified request * URI. If no matching Context can be found, return an appropriate HTTP error. * * @param request Request to be processed * @param response Response to be produced * @exception IOException if an input/output error occurred * @exception ServletException if a servlet error occurred */ @Override public final void invoke(Request request, Response response) throws IOException, ServletException { /* * xujb: * 和Engine一样,调用下层的context,让它来做一些处理 * 自身也处理了一些的逻辑 * * */ // Select the Context to be used for this Request Context context = request.getContext(); if (context == null) { response.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm.getString("standardHost.noContext")); return; } // Bind the context CL to the current thread if (context.getLoader() != null) { // Not started - it should check for availability first // This should eventually move to Engine, it's generic. if (Globals.IS_SECURITY_ENABLED) { PrivilegedAction<Void> pa = new PrivilegedSetTccl(context.getLoader().getClassLoader()); AccessController.doPrivileged(pa); } else { Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader()); } } if (request.isAsyncSupported()) { request.setAsyncSupported(context.getPipeline().isAsyncSupported()); } boolean asyncAtStart = request.isAsync(); boolean asyncDispatching = request.isAsyncDispatching(); if (asyncAtStart || context.fireRequestInitEvent(request)) { // Ask this Context to process this request. Requests that are in // async mode and are not being dispatched to this resource must be // in error and have been routed here to check for application // defined error pages. try { if (!asyncAtStart || asyncDispatching) { context.getPipeline().getFirst().invoke(request, response); } else { // Make sure this request/response is here because an error // report is required. if (!response.isErrorReportRequired()) { throw new IllegalStateException(sm.getString("standardHost.asyncStateError")); } } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); // If a new error occurred while trying to report a previous // error simply log the new error and allow the original error // to be reported. if (response.isErrorReportRequired()) { container.getLogger().error("Exception Processing " + request.getRequestURI(), t); } else { request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t); throwable(request, response, t); } } // Now that the request/response pair is back under container // control lift the suspension so that the error handling can // complete and/or the container can flush any remaining data response.setSuspended(false); Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION); // Protect against NPEs if the context was destroyed during a // long running request. if (!context.getState().isAvailable()) { return; } // Look for (and render if found) an application level error page if (response.isErrorReportRequired()) { if (t != null) { throwable(request, response, t); } else { status(request, response); } } if (!request.isAsync() && (!asyncAtStart || !response.isErrorReportRequired())) { context.fireRequestDestroyEvent(request); } } // Access a session (if present) to update last accessed time, based on a // strict interpretation of the specification if (ACCESS_SESSION) { request.getSession(false); } // Restore the context classloader if (Globals.IS_SECURITY_ENABLED) { PrivilegedAction<Void> pa = new PrivilegedSetTccl(StandardHostValve.class.getClassLoader()); AccessController.doPrivileged(pa); } else { Thread.currentThread().setContextClassLoader(StandardHostValve.class.getClassLoader()); } }
public void invoke(Request request, Response response, CompositeValve compositeValve) { String context = request.getContextPath(); if (context == null || context.equals("")) { // Invoke next valve in pipe. getNext().invoke(request, response, compositeValve); return; } boolean contextExist; Boolean contextValueInCache = null; if (APIUtil.getAPIContextCache().get(context) != null) { contextValueInCache = Boolean.parseBoolean(APIUtil.getAPIContextCache().get(context).toString()); } if (contextValueInCache != null) { contextExist = contextValueInCache; } else { contextExist = ApiMgtDAO.isContextExist(context); APIUtil.getAPIContextCache().put(context, contextExist); } if (!contextExist) { getNext().invoke(request, response, compositeValve); return; } handleWSDLGetRequest(request, response, compositeValve, context); long requestTime = System.currentTimeMillis(); APIManagerInterceptorOps interceptorOps = new APIManagerInterceptorOps(); UsageStatConfiguration statConfiguration = new UsageStatConfiguration(); if (contextExist) { // Use embedded WebApp Management if (log.isDebugEnabled()) { log.debug("WebApp Manager Interceptor Valve Got invoked!!"); } String bearerToken = request.getHeader(APIConstants.OperationParameter.AUTH_PARAM_NAME); String accessToken = null; /* Authenticate*/ try { if (bearerToken != null) { accessToken = APIManagetInterceptorUtils.getBearerToken(bearerToken); } else { // There can be some WebApp published with None Auth Type /* * throw new * APIFaultException(APIConstants.KeyValidationStatus * .API_AUTH_INVALID_CREDENTIALS, * "Invalid format for Authorization header. Expected 'Bearer <token>'" * ); */ } String apiVersion = APIManagetInterceptorUtils.getAPIVersion(request); String domain = request.getHeader(APITokenValidator.getAPIManagerClientDomainHeader()); String authLevel = authenticator.getResourceAuthenticationScheme( context, apiVersion, request.getRequestURI(), request.getMethod()); if (authLevel == APIConstants.NO_MATCHING_AUTH_SCHEME) { APIManagetInterceptorUtils.handleNoMatchAuthSchemeCallForRestService( response, request.getMethod(), request.getRequestURI(), apiVersion, context); return; } else { interceptorOps.doAuthenticate(context, apiVersion, accessToken, authLevel, domain); } } catch (APIManagementException e) { // ignore } catch (APIFaultException e) { /* If !isAuthorized APIFaultException is thrown*/ APIManagetInterceptorUtils.handleAPIFaultForRestService( e, APIManagerErrorConstants.API_SECURITY_NS, APIManagerErrorConstants.API_SECURITY_NS_PREFIX, response); return; } /* Throttle*/ try { interceptorOps.doThrottle(request, accessToken); } catch (APIFaultException e) { APIManagetInterceptorUtils.handleAPIFaultForRestService( e, APIManagerErrorConstants.API_THROTTLE_NS, APIManagerErrorConstants.API_THROTTLE_NS_PREFIX, response); return; } /* Publish Statistic if enabled*/ if (statConfiguration.isStatsPublishingEnabled()) { try { interceptorOps.publishStatistics(request, requestTime, false); } catch (APIManagementException e) { log.error("Error occured when publishing stats", e); } } } // Invoke next valve in pipe. getNext().invoke(request, response, compositeValve); // Handle Responses if (contextExist && statConfiguration.isStatsPublishingEnabled()) { try { interceptorOps.publishStatistics(request, requestTime, true); } catch (APIManagementException e) { log.error("Error occured when publishing stats", e); } } }
/** * Enforce any user data constraint required by the security constraint guarding this request URI. * Return <code>true</code> if this constraint was not violated and processing should continue, or * <code>false</code> if we have created a response already. * * @param request Request we are processing * @param response Response we are creating * @param constraints Security constraint being checked * @exception IOException if an input/output error occurs */ @Override public boolean hasUserDataPermission( Request request, Response response, SecurityConstraint[] constraints) throws IOException { // Is there a relevant user data constraint? if (constraints == null || constraints.length == 0) { if (log.isDebugEnabled()) log.debug(" No applicable security constraint defined"); return (true); } for (int i = 0; i < constraints.length; i++) { SecurityConstraint constraint = constraints[i]; String userConstraint = constraint.getUserConstraint(); if (userConstraint == null) { if (log.isDebugEnabled()) log.debug(" No applicable user data constraint defined"); return (true); } if (userConstraint.equals(Constants.NONE_TRANSPORT)) { if (log.isDebugEnabled()) log.debug(" User data constraint has no restrictions"); return (true); } } // Validate the request against the user data constraint if (request.getRequest().isSecure()) { if (log.isDebugEnabled()) log.debug(" User data constraint already satisfied"); return (true); } // Initialize variables we need to determine the appropriate action int redirectPort = request.getConnector().getRedirectPort(); // Is redirecting disabled? if (redirectPort <= 0) { if (log.isDebugEnabled()) log.debug(" SSL redirect is disabled"); response.sendError(HttpServletResponse.SC_FORBIDDEN, request.getRequestURI()); return (false); } // Redirect to the corresponding SSL port StringBuilder file = new StringBuilder(); String protocol = "https"; String host = request.getServerName(); // Protocol file.append(protocol).append("://").append(host); // Host with port if (redirectPort != 443) { file.append(":").append(redirectPort); } // URI file.append(request.getRequestURI()); String requestedSessionId = request.getRequestedSessionId(); if ((requestedSessionId != null) && request.isRequestedSessionIdFromURL()) { file.append(";"); file.append(SessionConfig.getSessionUriParamName(request.getContext())); file.append("="); file.append(requestedSessionId); } String queryString = request.getQueryString(); if (queryString != null) { file.append('?'); file.append(queryString); } if (log.isDebugEnabled()) log.debug(" Redirecting to " + file.toString()); response.sendRedirect(file.toString()); return (false); }
public boolean validate(Request request) { if ((userName == null) || (realmName == null) || (nonce == null) || (uri == null) || (response == null)) { return false; } // Validate the URI - should match the request line sent by client if (validateUri) { String uriQuery; String query = request.getQueryString(); if (query == null) { uriQuery = request.getRequestURI(); } else { uriQuery = request.getRequestURI() + "?" + query; } if (!uri.equals(uriQuery)) { // Some clients (older Android) use an absolute URI for // DIGEST but a relative URI in the request line. // request. 2.3.5 < fixed Android version <= 4.0.3 String host = request.getHeader("host"); String scheme = request.getScheme(); if (host != null && !uriQuery.startsWith(scheme)) { StringBuilder absolute = new StringBuilder(); absolute.append(scheme); absolute.append("://"); absolute.append(host); absolute.append(uriQuery); if (!uri.equals(absolute.toString())) { return false; } } else { return false; } } } // Validate the Realm name String lcRealm = getRealmName(request.getContext()); if (!lcRealm.equals(realmName)) { return false; } // Validate the opaque string if (!opaque.equals(opaqueReceived)) { return false; } // Validate nonce int i = nonce.indexOf(":"); if (i < 0 || (i + 1) == nonce.length()) { return false; } long nonceTime; try { nonceTime = Long.parseLong(nonce.substring(0, i)); } catch (NumberFormatException nfe) { return false; } String md5clientIpTimeKey = nonce.substring(i + 1); long currentTime = System.currentTimeMillis(); if ((currentTime - nonceTime) > nonceValidity) { nonceStale = true; synchronized (nonces) { nonces.remove(nonce); } } String serverIpTimeKey = request.getRemoteAddr() + ":" + nonceTime + ":" + key; byte[] buffer = ConcurrentMessageDigest.digestMD5(serverIpTimeKey.getBytes(StandardCharsets.ISO_8859_1)); String md5ServerIpTimeKey = MD5Encoder.encode(buffer); if (!md5ServerIpTimeKey.equals(md5clientIpTimeKey)) { return false; } // Validate qop if (qop != null && !QOP.equals(qop)) { return false; } // Validate cnonce and nc // Check if presence of nc and Cnonce is consistent with presence of qop if (qop == null) { if (cnonce != null || nc != null) { return false; } } else { if (cnonce == null || nc == null) { return false; } // RFC 2617 says nc must be 8 digits long. Older Android clients // use 6. 2.3.5 < fixed Android version <= 4.0.3 if (nc.length() < 6 || nc.length() > 8) { return false; } long count; try { count = Long.parseLong(nc, 16); } catch (NumberFormatException nfe) { return false; } NonceInfo info; synchronized (nonces) { info = nonces.get(nonce); } if (info == null) { // Nonce is valid but not in cache. It must have dropped out // of the cache - force a re-authentication nonceStale = true; } else { if (!info.nonceCountValid(count)) { return false; } } } return true; }