Javascript 处理资源URI中特殊字符的正确方法是什么?如何妥善逃生?
我们的应用程序通过AJAXJavascript 处理资源URI中特殊字符的正确方法是什么?如何妥善逃生?,javascript,angularjs,rest,spring-mvc,escaping,Javascript,Angularjs,Rest,Spring Mvc,Escaping,我们的应用程序通过AJAXGET请求实现API来访问实体细节——它曾经被使用过POST,但我们决定改变我们的标准 不幸的是,我们最近遇到了一个设计缺陷 假设我们的API是http://localhost/app/module/entity/detail/{id}其中{id}是与该实体的主键匹配的Spring@PathVariable 如果主键是数字代理键(自动递增),则没有问题。但我们认为这一切都可以通过String主键来实现 碰巧我们发现一些有效的生产数据包含斜杠、反斜杠和主键的分号。我们的表
GET
请求实现API来访问实体细节——它曾经被使用过POST
,但我们决定改变我们的标准
不幸的是,我们最近遇到了一个设计缺陷
假设我们的API是http://localhost/app/module/entity/detail/{id}
其中{id}
是与该实体的主键匹配的Spring@PathVariable
如果主键是数字代理键(自动递增),则没有问题。但我们认为这一切都可以通过String
主键来实现
碰巧我们发现一些有效的生产数据包含斜杠、反斜杠和主键的分号。我们的表无法使用自动增量代理键,因为它们的大小太大了
更一般地说,我们发现我们没有准备好处理非字母数字字符
缺陷代码最初是什么
下面是我们的应用程序如何在实体列表的单个页面中显示实体数据:
table.jsp
,通过POST检索AJAX列表detail?entityId={{{::row:idAttribute}}
detail?entityId=5903475934 //numeric case, we have several details page with same navigation pattern
detail?entityID=AAABBBCCC
detail?entityID=DO0000099101\test
@PathVariable
DO0000099101est
我们试图解决的问题
我们试图通过避开\t
来修复这个错误,因为它在HTML内容中的存在显然构成了一个bug。Javascript将其解释为一个选项卡
http://localhost/blablabla/detail?entityId=DO0000099101%5Ctest
通过将反斜杠转义到其URL实体。其目的是,如果这起作用,我们可以修改表格页面中的角度代码
结果是\t
再次出现,与Javascript片段中的一样。从这一点来看,顺序是相同的
<script type="text/javascript">
var ____entityId = 'DO0000099101\test';
</script>
http://localhost/app/module/entity/detail/{id}
,让我们试着看看Spring希望如何转义反斜杠
http://localhost/app/module/entity/detail/DO0000099101%5Ctest //results in 400 error
http://localhost/app/module/entity/detail/DO0000099101\\test //Chrome reversed the backslash into a forward slash and the result is 404 as expected for http://localhost/app/module/entity/detail/DO0000099101//test
$http.get($const.urlController+'detail/'+encodeURIComponent($scope.entityId))
这种方法的问题是URL中的反斜杠-T
序列被编码为%09
,这导致服务器端的选项卡被解码
使用encodeURIComponent和Java转义
现在我们尝试使用方法4和将硬编码的Java转义(即\\t
)修复到Javascript中进行测试
<script type="text/javascript">
var ____entityId = 'DO0000099101\\test';
</script>
$http.get($const.urlController+'detail/'+encodeURIComponent($scope.entityId))
质询时间
我想用两种方式问这个问题,一种是具体的,另一种是一般性的
具体:如何正确设置@PathVariable
的格式,使其能够保留特殊字符
常规:在其他情况下,在处理可能包含特殊字符的资源ID时需要注意什么
关于第二点,让我更清楚一点。如果您控制REST应用程序和ID的生成,则可以选择只允许字母数字标识符(用户生成的或随机的或任何形式的)和睡眠
但在我们的例子中,我们需要浏览来自外部系统的实体,这些系统对实体主标识符所允许的字符集有更广泛的限制。
同样,我们不能使用自动增量代理键。控制器:$const.urlController+'detail/'+encodeURIComponent($scope.entityId)
模板:我首先用结果扩展了我的问题,然后我将阅读链接文章如何将entityId
实际注入JS。如果\t
不应该是选项卡,则您的字符串是错误的。我不知道JSP,但我假设您正在执行类似于snippet='var\uuuuuuuuuuEntityId=“'+entityId+”;'
并将该片段插入到标记中?然后您应该将其更改为Java等效的snippet='var\uuuuuuuu entityId='+JSON.stringify(entityId)+';'
结合encodeURIComponent()
应该可以解决您的问题
http://localhost/blablabla/detail?entityId=DO0000099101%5C%5Ctest
<script type="text/javascript">
var ____entityId = 'DO0000099101\\test'; //Looks great
</script>
http://localhost/blablabla/detail/DO0000099101/test
http://localhost/app/module/entity/detail/DO0000099101%5Ctest //results in 400 error
http://localhost/app/module/entity/detail/DO0000099101\\test //Chrome reversed the backslash into a forward slash and the result is 404 as expected for http://localhost/app/module/entity/detail/DO0000099101//test
$http.get($const.urlController+'detail/'+encodeURIComponent($scope.entityId))
<script type="text/javascript">
var ____entityId = 'DO0000099101\\test';
</script>
$http.get($const.urlController+'detail/'+encodeURIComponent($scope.entityId))
http://localhost/app/module/entity/detail/DO0000099101%5Ctest //results in 400 error