如何实现REST资源的输入验证

如何实现REST资源的输入验证

我正在使用的SaaS平台具有一个RESTful接口,该接口可以接受XML有效负载。 剩余验证

实施REST资源

对于像我们这样的Java商店,使用JAX-B从XML Schema生成JavaBean类是有意义的。 在像Jersey的JAX-RS环境中,使用JAX-B处理XML(和JSON)有效负载非常容易。

@Path("orders")
public class OrdersResource {@POST@Consumes({ "application/xml", "application/json" })public void place(Order order) {// Jersey marshalls the XML payload into the Order // JavaBean, allowing us to write type-safe code // using Order's getters and setters.int quantity = order.getQuantity();// ...}
}

(请注意,您不应该使用这些通用媒体类型,但这是另一天的讨论。)

本文的其余部分假定使用JAX-B,但其要点也适用于其他技术。 无论您做什么,都不要使用XMLDecoder ,因为这对许多漏洞都是开放的 。

保护REST资源

假设订单的quantity用于结算,并且我们想防止人们输入负数来窃取我们的钱 。

我们可以通过输入验证 ( AppSec工具箱中最重要的工具之一)来做到这一点。 让我们看一下实现它的一些方法。

使用XML模式进行输入验证

XML模式 我们可以依靠XML Schema进行验证 ,但是XML Schema只能验证那么多。

验证单个属性可能会很好,但是当我们要验证属性之间的关系时,事情变得很麻烦。 为了获得最大的灵活性,我们希望使用Java来表达约束。

更重要的是, 在REST服务中模式验证通常不是一个好主意

REST的主要目标是使客户端和服务器脱钩,以便它们可以分别发展。

如果我们根据模式进行验证,则发送新属性的新客户端将与无法理解该新属性的旧服务器发生冲突。 通常最好静默忽略您不了解的属性。

JAX-B可以做到这一点,反之亦然:旧客户端未发送的属性最终为null 。 因此,新服务器必须小心以正确处理null值。

使用Bean验证的输入验证

豆验证 如果我们不能使用模式验证,那么使用JSR 303 Bean验证又如何呢?

Jersey通过将jersey-bean-validation jar添加到您的类路径来支持Bean验证。

有一个非官方的Maven插件可以将Bean验证注释添加到JAX-B生成的类中,但是我宁愿使用更好的支持,并且可以与Gradle一起使用 。

因此,让我们扭转局势。 我们将手工制作JavaBean并从Bean生成XML Schema进行文档编制:

@XmlRootElement(name = "order")
public class Order {@XmlElement@Min(1)public int quantity;
}
@Path("orders")
public class OrdersResource {@POST@Consumes({ "application/xml", "application/json" })public void place(@Valid Order order) {// Jersey recognizes the @Valid annotation and// returns 400 when the JavaBean is not valid}
}

任何企图POST与非阳性数量的订单,现在将给予400 Bad Request状态。

现在假设我们要允许客户更改其挂单。 我们将使用PATCHPUT更新单个订单属性,例如数量:

@Path("orders")
public class OrdersResource {@Path("{id}")@PUT@Consumes("application/x-www-form-urlencoded")public Order update(@PathParam("id") String id, @Min(1) @FormParam("quantity") int quantity) {// ...}
}

我们也需要在此处添加@Min注释,这是重复的。 为了使这个DRY ,我们可以将quantity变成负责验证的类:

@Path("orders")
public class OrdersResource {@Path("{id}")@PUT@Consumes("application/x-www-form-urlencoded")public Order update(@PathParam("id") String id, @FormParam("quantity")Quantity quantity) {// ...}
}
@XmlRootElement(name = "order")
public class Order {@XmlElementpublic Quantity quantity;
}
public class Quantity {private int value;public Quantity() { }public Quantity(String value) {try {setValue(Integer.parseInt(value));} catch (ValidationException e) {throw new IllegalArgumentException(e);}}public int getValue() {return value;}@XmlValuepublic void setValue(int value) throws ValidationException {if (value < 1) {throw new ValidationException("Quantity value must be positive, but is: " + value);}this.value = value;}
}

我们需要JAX-B的公共no-arg构造函数,以便能够将有效载荷解组到JavaBean中,而另一个构造函数则使用String来使@FormParam起作用。

setValue()抛出javax.xml.bind.ValidationException以便JAX-B将停止解组。 但是,Jersey看到异常时会返回500 Internal Server Error

我们可以通过使用异常映射器将验证异常映射到400状态代码来解决此问题。 在此过程中,让我们对IllegalArgumentException做同样的事情:

@Provider
public class DefaultExceptionMapper implements ExceptionMapper<Throwable> {@Overridepublic Response toResponse(Throwable exception) {Throwable badRequestException = getBadRequestException(exception);if (badRequestException != null) {return Response.status(Status.BAD_REQUEST).entity(badRequestException.getMessage()).build();}if (exception instanceof WebApplicationException) {return ((WebApplicationException)exception).getResponse();}return Response.serverError().entity(exception.getMessage()).build();}private Throwable getBadRequestException(Throwable exception) {if (exception instanceof ValidationException) {return exception;}Throwable cause = exception.getCause();if (cause != null && cause != exception) {Throwable result = getBadRequestException(cause);if (result != null) {return result;}}if (exception instanceof IllegalArgumentException) {return exception;}if (exception instanceof BadRequestException) {return exception;}return null;}}

域对象的输入验证

http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-ebook/dp/B00794TAUG/ref=tmm_kin_title_0?ie=UTF8&qid=1376856556&sr=1-1 即使上面概述的方法对于许多应用程序都可以很好地工作,但从根本上来说还是有缺陷的。

乍一看, 领域驱动设计 (DDD)的支持者可能喜欢创建“ Quantity类的想法。

但是,“ Order和“ Quantity类不能为领域概念建模。 他们为REST表示建模。 这种区别可能很微妙,但很重要。

DDD处理领域概念,而REST处理这些概念的表示 发现了领域概念,但是设计了表示形式,并且需要进行各种折衷。

例如,集合REST资源可以使用分页来防止通过网络发送太多数据。 另一个REST资源可能结合了多个域概念,以使客户端-服务器协议的聊天性降低。

REST资源甚至可能根本没有对应的域概念。 例如,一个POST可能返回202 Accepted并指向代表异步事务进度的REST资源。

无处不在的语言 域对象需要尽可能接近地捕获普遍存在的语言 ,并且必须权衡利弊才能使功能起作用。

另一方面,在设计REST资源时,需要权衡满足非功能性需求,例如性能,可伸缩性和可扩展性。

这就是为什么我认为像RESTful Objects这样的方法不起作用的原因。 (出于类似原因,我不相信UI的Naked Objects 。)

在我们的资源表示形式的JavaBeans中添加验证意味着这些bean现在有两个更改的原因,这明显违反了“ 单一职责原则” 。

当仅将JAX-B JavaBeans用于REST表示并创建处理验证的单独域对象时,我们得到的架构会更简洁。

将验证放在域对象中是Dan Bergh Johnsson所谓的“ 域驱动的安全性” 。

洞穴艺术 在这种方法中,原始类型被值对象替代。 (甚至有人反对使用任何String 。)

起初,创建一个用于容纳单个整数的全新类似乎有些矫kill过正,但是我敦促您尝试一下。 您可能会发现,摆脱原始的迷恋甚至可以提供超出验证的价值。

你怎么看?

您如何在RESTful服务中处理输入验证? 您如何看待域驱动的安全性? 请发表评论。

参考: 如何从安全软件开发博客上的JCG合作伙伴 Remon Sinnema 获得REST资源的输入验证 。

翻译自: https://www.javacodegeeks.com/2013/08/how-to-implement-input-validation-for-rest-resources.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367133.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统下,MySQL以及禅道的安装/卸载

1、MySQL卸载&#xff1a; &#xff08;通过yum命令卸载之前安装的mysql&#xff0c; find命令找到mysql文件&#xff0c;再用rm –rf 强制删除/var/lib/mysql&#xff09; 2、MySQL安装&#xff1a; &#xff08;使用yum命令安装mysql&#xff0c;安装完成后启动数据库&#x…

python类对象点处折行_史上最全的Python面向对象知识点疏理(对象是类的实例)

(对象是类的实例)面向对象技术简介类:用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。class类变量&#xff1a;类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用…

winform 点击全选

代码如下&#xff1a; #region 全选//chkAll_Checked即全选控键的点击事件private void chkAll_CheckedChanged(object sender, EventArgs e){if (chkAll.Checked){chkSun.Checked true;chkMon.Checked true;chkThu.Checked true;chkTue.Checked true;chkWed.Checked true…

今天的考核题目: 你知道React和Vue的区别吗? skr,skr

React 和 Vue 的区别 博主面了几家公司&#xff0c;看简历上写着使用Vue.js框架&#xff0c;就会问&#xff0c;你能说一说 vue 和 react的区别吗 &#xff1f;react 听过&#xff0c;没用过&#xff0c;所以就只能尴尬的说不怎么了解react。这不&#xff0c;最近刚学了react …

Play和Grails Java框架的优缺点

框架通过为程序员提供一些有用的功能来简化应用程序开发过程。 由于开发人员的普遍使用&#xff0c;Java框架经常被开发人员使用。 您可以在市场上找到各种Java开发框架。 新手开发人员经常在论坛上发布一个常见问题&#xff1a;“哪种Java框架是最好的&#xff1f;” 首先&am…

C++小项目-吃豆子游戏

GMap.h #pragma once //保证头文件只被编译一次#include "stdafx.h"#define MAP_LEN 19 //逻辑地图大小 (逻辑地图由行、列各为19的方块组成)#define P_ROW 10 //大嘴出生地的横逻辑坐标 #define P_COLUMN 9 //大嘴出生地的列逻辑坐标 #define E_ROW 8 //敌人出…

argb888与rgb888转换程序_一文了解各平台RGB565和RGB888区别

原标题&#xff1a;一文了解各平台RGB565和RGB888区别用过AM335x平台的小伙伴应该知道&#xff0c;OK335xS开发平台的LCD接口是RGB888模式的&#xff0c;而OK335xD开发平台的LCD接口是RGB565模式的。如果把xS的镜像烧写到xD平台上&#xff0c;那么LCD会显示颜色异常。这是为什么…

d4d#9 玩Docker只要浏览器就够了,PWD是个神奇的网站

本文是d4d系列的第9篇&#xff0c;在这一篇中给大家介绍一个学习Docker最为快捷高效的方式&#xff0c;你不需要自己搭建环境&#xff0c;也不用担心把自己的开发环境搞乱&#xff0c;你需要的只是一个浏览器&#xff0c;就可以立即开始学习Docker的常用命令&#xff1b;你甚至…

基于 Docker 打造前端持续集成开发环境

知乎: https://zhuanlan.zhihu.com/p/37961402本文将以一个标准的 Vue 项目为例&#xff0c;完全抛弃传统的前端项目开发部署方式&#xff0c;基于 Docker 容器技术打造一个精简的前端持续集成的开发环境。 前置知识&#xff1a;1. CI&#xff08;持续集成&#xff09;&#xf…

哪个内存更快?Heap或ByteBuffer或Direct?

Java正在成为新的C / C &#xff0c;它被广泛用于开发高性能系统。 对像我这样的数百万Java开发人员来说非常好&#xff01; 在这个博客中&#xff0c;我将分享我可以用Java完成的不同类型的内存分配实验以及您从中获得的好处。 Java中的内存分配 Java提供哪种类型的内存分配…

java没有打印mysql日志_0216 aop和打印数据库执行日志

需求maven依赖p6spyp6spy3.8.7com.google.guavaguava28.2-jreorg.springframework.bootspring-boot-starter-data-jpaorg.springframework.bootspring-boot-starter-webmysqlmysql-connector-javaruntimeorg.projectlomboklomboktrue打印sql配置要点&#xff1a;驱动配置 appli…

php数组基础

php中&#xff0c;数组的下标可以是整数&#xff0c;或字符串。 php中&#xff0c;数组的元素顺序不是由下标决定&#xff0c;而是由其“加入”的顺序决定。 定义&#xff1a; $arr1 array(元素1&#xff0c;元素2&#xff0c;。。。。。 ); array(1, 5, 1.1, “abc”, tr…

1.格式化输入输出

1.格式化输入input() input()函数&#xff0c;通常只能返回一个数据类型&#xff0c;那么怎么可以进行多个变量的复制呢&#xff1f;看下面这段代码。 1 str1, str2 eval(input("请输入两个字符串&#xff1a;")) 2 print(str1, str2) 3 4 num1, num2 eval(input(…

canvas像素点操作 —— 视频绿幕抠图

原文地址 主要内容 上篇文章学习了canvas像素点的获取 —— 传送门&#xff0c; 今天学一下canvas像素点操作。 一个方法&#xff1a;putImageData putImageData 用法&#xff1a; context.putImageData(imgData, x, y, dX, dY, dWidth, dHeight);参数描述imgData规定要放…

Java中的迭代器设计模式–示例教程

迭代器模式是一种行为模式&#xff0c;用于提供遍历一组对象的标准方式。 Iterator模式在Java Collection Framework中得到了广泛使用&#xff0c;其中Iterator接口提供了遍历集合的方法。 根据GoF&#xff0c;迭代器设计模式的意图是&#xff1a; 提供一种在不暴露其基础表示…

random

1 import random2 3 result random.randint(1, 7) # 随机生成1到7的整数4 result random.random() # 随机生成[0,1)的浮点数5 result random.randrange(1, 7) # 随机生成1到7的整数6 result random.choice([1, 2, 3, 4]) # 从列表中随机选择一个元素7 result random.c…

面向对象 解释 经典啊

想必大家都知道面向对象三大特征&#xff1a;继承&#xff0c;封装&#xff0c;多态。 假如你现在有一个女朋友&#xff0c;那么现在你就可以称呼你的女朋友为对象啦。首先&#xff0c;你女朋友的身高三围等我们称作为属性&#xff0c;你如果想要跟你好基友分享一下你女朋友的身…

关于Unity实现AR功能(五)摄像头转换与闪光灯开关控制

1 /// <summary>2 /// 摄像头转换3 /// </summary>4 /// <param name"s_cameraDirection">摄像头转换方向</param>5 public void ChangeCameraDirectionMet(CameraDevice.CameraDirection s_cameraDirection)6 {7 …

并发编程(一):基础概述

本篇博客主要讲述并发编程中的一些基础内容&#xff0c;并了解一下基本概念。 首先我们了解一下什么是并发&#xff1f; 同时拥有两个或者多个线程&#xff0c;如果程序在单核处理器上运行&#xff0c;多个线程将交替的换入或者换出内存&#xff0c;这些线程是同时“存在”的&a…

Dumb Bones UVA - 10529(概率dp)

题意&#xff1a; 你试图把一些多米诺骨牌排成直线&#xff0c;然后推倒它们。但是如果你在放骨牌的时候不小心把刚放的骨牌碰倒了&#xff0c;它就会把相临的一串骨牌全都碰倒&#xff0c; 而你的工作也被部分的破坏了。 比如你已经把骨牌摆成了DD__DxDDD_D的形状&#xff0c;…