Un API es un contrato entre un autor de llamada y un receptor de llamada. Las formas de abuso de API más comunes los produce el autor de llamada cuando no consigue atender su fin de este contrato. Por ejemplo, si un programa no consigue llamar chdir() después de llamar chroot(), se viola el contrato que especifica cómo cambiar el directorio de origen activo de una forma segura. Otro buen ejemplo de un abuso de manual es esperar que el receptor devuelva una información de DNS de confianza al autor de llamada. En este caso, el autor de llamada abusa el API del receptor haciendo determinadas suposiciones sobre su comportamiento (que el valor de retorno se puede usar con fines de autenticación). También se puede violar el contrato entre el autor de llamada y el receptor desde el otro lado. Por ejemplo, si un codificador envía SecureRandom y devuelve un valor no aleatorio, se viola el contrato.
Code Correctness: Multiple Stream Commits
getWriter()
después de haber llamado getOutputStream
o viceversa.HttpServletRequest
, redirigir una HttpServletResponse
o vaciar el flujo de salida del servlet provoca la confirmación del flujo asociado. Todo restablecimiento de búfer o confirmación de flujo, como los vaciados o los redireccionamientos adicionales, provocarán una IllegalStateException
s.Además, los servlets de Java permiten que los datos se escriban en el flujo de respuesta empleando
ServletOutputStream
o PrintWriter
, pero no ambos. Llamar getWriter()
después de haber llamado getOutputStream()
, o viceversa, también provocará una IllegalStateException
.En tiempo de ejecución, una
IllegalStateException
impide que el controlador de respuesta se ejecute hasta la finalización, entregando la respuesta de forma eficaz. Esto puede causar inestabilidad en el servidor, señal de que un servlet se ha implementado incorrectamente.Ejemplo 1: el código siguiente redirige la respuesta del servlet después de que su búfer de flujo de salida se haya vaciado.
Ejemplo 2: por otra parte, el código siguiente intenta escribir en el búfer de
public class RedirectServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
...
OutputStream out = res.getOutputStream();
...
// flushes, and thereby commits, the output stream
out.flush();
out.close(); // redirecting the response causes an IllegalStateException
res.sendRedirect("http://www.acme.com");
}
}
PrintWriter
y vaciarlo después de que la solicitud se haya enviado.
public class FlushServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
...
// forwards the request, implicitly committing the stream
getServletConfig().getServletContext().getRequestDispatcher("/jsp/boom.jsp").forward(req, res);
...
// IllegalStateException; cannot redirect after forwarding
res.sendRedirect("http://www.acme.com/jsp/boomboom.jsp");
PrintWriter out = res.getWriter();
// writing to an already-committed stream will not cause an exception,
// but will not apply these changes to the final output, either
out.print("Writing here does nothing");
// IllegalStateException; cannot flush a response's buffer after forwarding the request
out.flush();
out.close();
}
}