Anotación @RequestParam para parámetros opcionales
INTEGRIDAD
Los parámetros anotados con @RequestParam son opcionales si se indica a través del atributo required = false de la anotación @RequestParam.
Este requisito corrige las vulnerabilidades
Command Injection
Cross-Site Scripting (XSS)
Unvalidated Redirects and Forwards
Insufficient Attack Protection
Underprotected APIs
Descripción
Los parámetros RequestParam opcionales:
Tienen valor por defecto vacío ("") si son de tipo String. Pueden anotarse con @NotBlank para indicar que no pueden estar en blanco (" ").
Tienen valor por defecto nulo si son de tipo colección (por ejemplo, List). Pueden anotarse con @NotEmpty para indicar que no deben ser nulo ni estar vacíos. Es decir, que deben contener al menos un elemento.
Tienen valor por defecto nulo en el resto de casos, excepto si son de tipo primitivo. Salvo en este caso, pueden anotarse con @NotNull para indicar que no deben ser nulo.
Los parámetros de tipo primitivo (byte, short, int, long, float, double, boolean, char) no pueden ser null en ningún caso.
El valor por defecto de cada parámetro puede modificarse a través del atributo defaultValue de la anotación @RequestParam.
Los parámetros opcionales que se anoten con @NotNull, @NotEmpty, @NotBlank, o que sean de tipo primitivo, deben tener especificado un valor por defecto que no esté vacío ("") ni en blanco (" "), dado que de lo contrario, se generará una excepción si no se introduce el parámetro en la petición.
Ejemplo incorrecto
/**
* Ejemplos de parámetros RequestParam opcionales incorrectos.
*
* @param optionalRequestParamStringNotBlank1
* Parámetro RequestParam opcional de tipo String que no puede estar en blanco.
* Le falta el atributo defaultValue de la anotación @RequestParam.
* @param optionalRequestParamStringNotBlank2
* Parámetro RequestParam opcional de tipo String que no puede estar en blanco.
* Su atributo defaultValue de la anotación @RequestParam no debe estar en blanco.
* @param optionalRequestParamListNotEmpty1
* Parámetro RequestParam opcional de tipo List que no puede estar vacío.
* Le falta el atributo defaultValue de la anotación @RequestParam.
* @param optionalRequestParamListNotEmpty2
* Parámetro RequestParam opcional de tipo List que no puede estar vacío.
* Su atributo defaultValue de la anotación @RequestParam no debe estar vacío.
* @param optionalRequestParamGenericNotNull1
* Parámetro RequestParam opcional de tipo genérico que no puede ser nulo.
* Le falta el atributo defaultValue de la anotación @RequestParm.
* @param optionalRequestParamGenericNotNull2
* Parámetro RequestParam opcional de tipo genérico que no puede ser nulo.
* Su atributo defaultValue de la anotación @RequestParm no debe estar vacío.
* @param optionalRequestParamPrimitive1
* Parámetro RequestParam opcional de tipo primitivo.
* Le falta el atributo defaultValue de la anotación @RequestParam.
* @param optionalRequestParamPrimitive2
* Parámetro RequestParam opcional de tipo primitivo. Su atributo defaultValue de la
* anotación @RequestParm no debe estar vacío.
* @return Response entity con los valores de los parámetros de entrada.
*/
@RequestMapping(value = "/optional-request-params", method = RequestMethod.GET)
public ResponseEntity<Map<String, Object>> optionalRequestParams(
@RequestParam(name = "optional-request-param-string-not-blank-1", required = false) @NotBlank String optionalRequestParamStringNotBlank1,
@RequestParam(name = "optional-request-param-string-not-blank-2", required = false, defaultValue = " ") @NotBlank String optionalRequestParamStringNotBlank2,
@RequestParam(name = "optional-request-param-list-not-empty-1", required = false) @NotEmpty List<?> optionalRequestParamListNotEmpty1,
@RequestParam(name = "optional-request-param-list-not-empty-2", required = false, defaultValue = "") @NotEmpty List<?> optionalRequestParamListNotEmpty2,
@RequestParam(name = "optional-request-param-generic-not-null-1", required = false) @NotNull Long optionalRequestParamGenericNotNull1,
@RequestParam(name = "optional-request-param-generic-not-null-2", required = false, defaultValue = "") @NotNull Long optionalRequestParamGenericNotNull2,
@RequestParam(name = "optional-request-param-primitive-1", required = false) boolean optionalRequestParamPrimitive1,
@RequestParam(name = "optional-request-param-primitive-2", required = false, defaultValue = "") boolean optionalRequestParamPrimitive2) {
...
}
Ejemplo correcto
/**
* Ejemplos de parámetros RequestParam opcionales.
*
* @param optionalRequestParamString
* Parámetro RequestParam opcional de tipo String con valor por defecto vacío.
* @param optionalRequestParamStringNotBlank
* Parámetro RequestParam opcional de tipo String que no puede estar en blanco.
* @param optionalRequestParamList
* Parámetro RequestParam opcional de tipo List con valor por defecto nulo.
* @param optionalRequestParamListNotEmpty
* Parámetro RequestParam opcional de tipo List que no puede estar vacío.
* @param optionalRequestParamGeneric
* Parámetro RequestParam opcional de tipo genérico con valor por defecto nulo.
* @param optionalRequestParamGenericNotNull
* Parámetro RequestParam opcional de tipo genérico que no puede ser nulo.
* @param optionalRequestParamPrimitive
* Parámetro RequestParam opcional de tipo primitivo.
* @return Response entity con los valores de los parámetros de entrada.
*/
@RequestMapping(value = "/optional-request-params", method = RequestMethod.GET)
public ResponseEntity<Map<String, Object>> optionalRequestParams(
@RequestParam(name = "optional-request-param-string", required = false) String optionalRequestParamString,
@RequestParam(name = "optional-request-param-string-not-blank", required = false, defaultValue = "a") @NotBlank String optionalRequestParamStringNotBlank,
@RequestParam(name = "optional-request-param-list", required = false) List<?> optionalRequestParamList,
@RequestParam(name = "optional-request-param-list-not-empty", required = false, defaultValue = "a") @NotEmpty List<?> optionalRequestParamListNotEmpty,
@RequestParam(name = "optional-request-param-generic", required = false) Long optionalRequestParamGeneric,
@RequestParam(name = "optional-request-param-generic-not-null", required = false, defaultValue = "1") @NotNull Long optionalRequestParamGenericNotNull,
@RequestParam(name = "optional-request-param-primitive", required = false, defaultValue = "true") boolean optionalRequestParamPrimitive) {
...
}
Cumplimiento de estándares y normativas
OWASP | OWASP [Top10/2016] A1 - Injection (in part) |
---|
Referencias
OWASP Top 10 Proactive Controls 2016:
https://www.owasp.org/index.php/OWASP_Proactive_Controls#tab=OWASP_Proactive_Controls_2016
OWASP Top 10 Proactive Controls 2016 Mapping:
https://www.owasp.org/index.php/OWASP_Proactive_Controls#tab=Top_10_Mapping_2016
OWASP Top 10 2017:
https://www.owasp.org/index.php/Top_10_2017-Top_10