如何在 Azure 中允许 URL 编码的路径段
Posted
技术标签:
【中文标题】如何在 Azure 中允许 URL 编码的路径段【英文标题】:How do I allow URL encoded path segments in Azure 【发布时间】:2016-05-12 06:32:39 【问题描述】:我有一个在 Azure 中运行的 ASP.NET 6 MVC 应用程序。我有一个控制器,其动作类似于
[HttpDelete]
[Route("image_url")]
public async Task<IActionResult> RemoveImageUrl([FromRoute(Name = "image_url")] String imageUrlString)
然后我就这样称呼它
api/https%3A%2F%2Frepocreator.zoltu.io%2Fimages%2FZoltu-Logo-Full-Size.png"
当使用 Kestrel 自托管时,此应用程序运行良好,但一旦我部署到 Azure,我就会收到 500 个错误。我已经尽可能多地进行了调试,经过大量的谷歌搜索和戳,似乎 IIS 正在尝试对请求进行有用的 URL 解码,然后再将其转发到 ASP.NET 进行处理。当然,问题是即使我可以说服 IIS 接受请求
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>
</system.webServer>
<system.web>
<httpRuntime requestValidationMode="2.0" requestPathInvalidCharacters="" relaxedUrlToFileSystemMapping="true"/>
<pages validateRequest="false" />
</system.web>
它仍然对 URL 进行解码,并将解码后的 URL 传递给 ASP.NET,它没有找到匹配的路由。
我能做些什么来告诉 IIS 停止在这里提供帮助,而只是传递它获得的任何 URL,而不进行任何形式的预验证或重写?注意:这是一个 Azure Web App,所以我无法直接访问 IIS 设置。
【问题讨论】:
Micah,我遇到了类似的问题...你有没有想出一个令人满意的解决方案? 我最终找到的解决方案是停止使用 IIS 托管。我不记得我是否解决了这个 specific 解决方案,但总的来说 IIS 最终比它的价值更痛苦。我现在用 Kestrel 在 docker 中运行我所有的东西,我的生活变得简单多了。 哈。好的,谢谢。 2019 年了,这仍然是个问题 smh 我最终只是对一些 url 参数进行了 b64 编码 【参考方案1】:您可以更新您的路线定义,使其与解码的图像 url 参数相匹配。
根据the documentation,在定义路由模板时:
您可以使用 * 字符作为路由值名称的前缀来绑定 到 URI 的其余部分。例如, blog/*slug 将匹配任何 URI 以 /blog/ 开头并在其后有任何值(这将 分配给 slug 路线值)。
所以你可以创建一个匹配路由[Route("*image_url")]
的动作:
[Route("*image_url")]
public IActionResult RemoveImageUrl([FromRoute(Name = "image_url")]String imageUrlString)
return Json(new ReceivedImage = imageUrlString );
我看到的唯一问题是协议部分被解码为http:/
,带有一个/
。你有几个选择:
您可以在控制器中手动修复它。更好的是,您可以创建一个模型绑定器和一个参数约定来自动执行此操作:
[HttpDelete]
[Route("*image_url")]
public IActionResult RemoveImageUrl([FullUrlFromEncodedRouteParam(Name = "image_url")] String imageUrlString)
return Json(new ReceivedImage = imageUrlString );
public class FullUrlFromUrlEncodedPathSegmentModelBinder : IModelBinder
//Matches a url that starts with protocol string and is followed by exactly ":/" instead of "://"
private static Regex incorrectProtocolRegex = new Regex(@"^([a-z][\w-]+:)\/1(?!\/)");
//A url path included as a url encoded path segment like http://localhost:39216/image2/https%3A%2F%2Frepocreator.zoltu.io%2Fimages%2FZoltu-Logo-Web.png
//will be decoded by IIS as https:/repocreator.zoltu.io/images/Zoltu-Logo-Web.png, note the single '/' after the protocol
//This model binder will fix it replacing "http:/" with "http://"
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
if (bindingContext.ValueProvider.GetValue(bindingContext.ModelName) == null)
return Task.FromResult(ModelBindingResult.NoResult);
var val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).FirstValue as string;
var fixedVal = incorrectProtocolRegex.Replace(val, @"$1//");
return Task.FromResult(ModelBindingResult.Success(bindingContext.ModelName, fixedVal));
public class FullUrlFromEncodedRouteParamAttribute : Attribute, IParameterModelConvention
public string Name get; set;
public void Apply(ParameterModel parameter)
parameter.BindingInfo = parameter.BindingInfo ?? new BindingInfo();
parameter.BindingInfo.BinderModelName = Name;
parameter.BindingInfo.BindingSource = BindingSource.Path;
parameter.BindingInfo.BinderType = typeof(FullUrlFromUrlEncodedPathSegmentModelBinder);
更好的方法可能是更新您的 api,这样您甚至不使用图像密钥中的协议部分。这将允许您在需要呈现完整图像 url 时添加正确的协议,具体取决于它是否需要 http 或 https(甚至可以从 url 中省略主机)。您甚至不需要担心在客户端对图像路径进行 url 编码,您可以像 http://localhost:39216/api/repocreator.zoltu.io/images/Zoltu-Logo-Full-Size.png
一样调用它。
恕我直言,我更喜欢第二种方法。如果你真的需要在路由中编码的完整 url,那么至少你有办法在控制器之外以干净的方式实现它。
注意:如果要保留图片url中的协议部分,看起来静态文件中间件不喜欢它们,所以必须在Startup.configure的MVC之后添加,否则它会抛出错误。
【讨论】:
虽然您的建议可以让我解决当前的问题(前端和后端都进行了更改),但它并没有解决根本问题,即如何在 Azure 中制作 IIS NOT URL 解码请求,然后将其传递给我的框架。 IIS 的行为违反了 URL 规范,我真的想要一种方法来使用 URL 编码的设计方式,并且以一种可跨 Web 服务器移植且灵活的方式(API 用户不必知道IIS)。 我同意它不会改变 Azure 处理 url 的方式,但用户不需要了解 Azure 的细节不是吗?http://localhost:39216/api/repocreator.zoltu.io%2Fimages%2FZoltu-Logo-Full-Size.png
和 http://localhost:39216/api/repocreator.zoltu.io/images/Zoltu-Logo-Full-Size.png
都可以正常工作。
除非我误解了您的建议,否则如果我的 API 用户使用 .../api/https%3A%2F%2Frepocreator.zoltu.io%2Fimages%2FZoltu-Logo-Web.png
调用它,事情将会崩溃,因为 IIS 会误解 URL 编码 //
。这意味着行为合理的用户将失败,因为后端恰好在 IIS 上运行(并且未正确处理 URL 编码)。如果后端在 Kestrel 上运行,则请求将是有效的。
是的,如果你真的想在 api 中包含协议,那么你就会遇到这个问题(你仍然可以在控制器中修复)。但是,如果用户不需要对完整路径进行 url 编码,甚至不需要担心协议或主机,恕我直言是一件好事(如dropbox api v1 或api v2)。如果您更改主机或使用 https,这些图像会怎样?以上是关于如何在 Azure 中允许 URL 编码的路径段的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Elastic Beanstalk 负载均衡器环境中允许编码斜杠