7

我正在 ASP.net 中实现 URL 重写,我的 URL 给我带来了很多问题。

URL 是从部门和类别的数据库中生成的。我希望员工能够使用任何适当的特殊字符将项目添加到数据库中,而不会破坏网站。

我在构建 URL 之前对数据进行编码。

有几个问题...

  1. IIS 在 URL 到达 .net 之前对其进行解码,因此无法正确解析其中包含“/”的任何内容。
  2. ASP.net 被 url 弄糊涂了,使得“~”在某些页面中无用
  3. 我从内置测试服务器迁移到我的本地 IIS 服务器(XP 机器),任何包含编码 & (%26) 的 URL 都会给我一个“错误请求”错误。
  4. UrlEncode 保留了一些中断字符,例如“。”

我确实有另外两个关于这个主题的相关帖子,当时我只看到了上游的小问题而不是大问题。我找到了一些注册表技巧来解决“错误请求”问题,但我将部署到共享托管环境,这使得它变得毫无用处。我也知道这是对某些安全问题的修复,所以我不想在不知道我打开什么蠕虫的情况下绕过它。

与其试图强制 .net 将原始 url 传递给我,或者覆盖 IIS 设置,不如首先创建真正安全的 URL。

我会注意到我已经尝试过 AntiXss.URLEncode、HttpUtility.URLEncode、URI.EscapeDataString。我什至尝试过双 URLEncodng 之类的愚蠢操作。是否有一个实用程序可以满足我的需要,或者我真的需要自己动手。我什至正在考虑做一些 Hacky 的事情,比如用不寻常的字符串替换 %。最终结果应该至少是可读的,这是首先使用 URL 重写的重点。

很抱歉发了这么长的帖子——我只是想确保我已经包含了所有必要的细节。我似乎找不到任何相关信息,而且这似乎是一个常见问题 - 所以也许我错过了一些大问题。感谢您的帮助,以及对冗长解释的耐心!


为清楚起见进行编辑:

当我说 url 是从数据库构建的时,我的意思是目录结构是从我的数据库中的部门和类别构建的。

一些示例 URL -

Mystore/Refrigeration/Bar+Fridge.aspx
Mystore/Cooking+Equipment.aspx
Mystore/Kitchen/Cutting+Boards.aspx

当我使用“Beverage & Bar”或“Pastry/Decorating”之类的部门来构建我的 URL 时,问题就出现了。尽管首先被编码,但这些会导致上述问题。

除了特殊字符编码问题外,我的处理程序已经实现并且工作正常。

4

4 回答 4

5

您应该考虑在您的类别/部门表中创建一个表,其中每个类别都有一个唯一的 URL。然后,您可以使用特殊的例程来生成 URL。这可以是 SQL 标量函数,也可以是 CLR 函数,但它要做的事情之一是规范化 Web 的 URL。您可以将“Beverage & Bar”转换为“Beverage-And-Bar”,将“Pastry / Decorating”转换为“Pastry-Decorating”。主要是,例程需要用其他东西替换所有无效的 HTTP URL 字符。一个例子是这样的:

public static class URL
{
    static readonly Regex feet = new Regex(@"([0-9]\s?)'([^'])", RegexOptions.Compiled);
    static readonly Regex inch1 = new Regex(@"([0-9]\s?)''", RegexOptions.Compiled);
    static readonly Regex inch2 = new Regex(@"([0-9]\s?)""", RegexOptions.Compiled);
    static readonly Regex num = new Regex(@"#([0-9]+)", RegexOptions.Compiled);
    static readonly Regex dollar = new Regex(@"[$]([0-9]+)", RegexOptions.Compiled);
    static readonly Regex percent = new Regex(@"([0-9]+)%", RegexOptions.Compiled);
    static readonly Regex sep = new Regex(@"[\s_/\\+:.]", RegexOptions.Compiled);
    static readonly Regex empty = new Regex(@"[^-A-Za-z0-9]", RegexOptions.Compiled);
    static readonly Regex extra = new Regex(@"[-]+", RegexOptions.Compiled);

    public static string PrepareURL(string str)
    {
        str = str.Trim().ToLower();
        str = str.Replace("&", "and");

        str = feet.Replace(str, "$1-ft-");
        str = inch1.Replace(str, "$1-in-");
        str = inch2.Replace(str, "$1-in-");
        str = num.Replace(str, "num-$1");

        str = dollar.Replace(str, "$1-dollar-");
        str = percent.Replace(str, "$1-percent-");

        str = sep.Replace(str, "-");

        str = empty.Replace(str, string.Empty);
        str = extra.Replace(str, "-");

        str = str.Trim('-');
        return str;
    }
}

您可以将此作为 SQL 增强功能,或将 URL 生成作为单独的进程运行。然后要实现映射,您可以将整个 URL 直接映射到类别 ID。从长远来看,这种方法更好,原因有几个。首先,您并不总是生成 URL,您只需执行一次,它们就会保持静态,您不必担心您的程序会发生变化,然后 GoogleBot 就无法找到旧的 URL。此外,如果您遇到冲突,您可能会注意到潜在的重复类别名称,因为冲突只会因特殊字符而有所不同。最后,您始终可以从数据库中查看您的 URL,而无需运行映射功能。

于 2009-08-17T16:45:04.287 回答
2

我在开始认证请求的 global.asax 文件中实现了 url 重写,因为我有一些安全性。这是我获取原始网址然后进行数据库查找的地方。然后,这会重写 aspx 页面的路径,并且所有参数都通过查询字符串传递。无需编码。

但是,如果您使用 url 来实际更改数据,那么我可以看到您将遇到巨大的问题,因为您正在有效地使用 http GET 来更改数据库。这通常被认为是一个坏主意,而不是我做的事情。

我只使用发布请求来进行任何数据库操作。这使 url 保持干净,因为所有数据都在页面表单中。

我唯一遇到的问题是将正确的 url 设置为 page.form.action,在大多数情况下是原始 url。

如果它是导致问题的类别名称,那么也许您应该将名称限制为仅字母数字字符并将空格交换为“-”。IIS 将抛出带有句点“。”的摇摆不定。因为它寻找文件名。

PS IIS 不理解波浪号“~”,这是编译器可以理解的。因此,如果您在锚标记中使用它,它将无法按预期工作,您应该使用应用程序根而不是波浪号。

编辑:

好的,看起来 IIS 存在某些字符问题,例如 . / 和 &。即使您对这些 IIS 进行了 urlencode,它们仍然会尝试实现其自身的含义。因此,请考虑删除它们:

Beverage & bar 变成 BeverageBar

糕点/装饰变成 PastryDecorating。

这将使您的网址保持干净,但确实意味着数据库中有一个额外的列,因此您可以根据这个缩短的类别名称检查网址。

于 2009-08-17T15:57:04.227 回答
1

我有完全相同的问题。谢谢你写得这么好。它实际上帮助我更好地理解了这个问题。

不过,我还有其他一些考虑。我的目标之一是支持任何字符出现在基于文章标题的 url 中的可能性。此外,我想确保编码和双向编码/解码过程的唯一性。

所以我做了一些手动编码来解决这个问题。这不会完全消除百分比编码,但会大大减少它并防止用户生成无法访问的 url。我的过程从使用该Server.URLEncode功能开始。但这并不能消除 url 中的问题。因为 IIS 正在解码 url,然后将其传递给应用程序,某些字符会以危险的请求异常破坏它。这些字符包括+, &, /, !, *, ., (). 因此,在这些字符和其他字符上,我想让它们更具可读性,我对更有用的 url 进行了双重编码。由于 url 中允许的字符数量有限,编码也很困难。因此,在编码之前,我将所有字母都设为大写,然后用小写进行编码。这使它无法完全解码,但我可以通过将我希望匹配的值设为大写来轻松地在数据库或代码中进行匹配。

好吧,这是我的代码。反馈将不胜感激。哦,是的,这是在 VB 中,但事情应该很容易转移到 C# 中。

Dim strReturn As String = Trim(strStringToEncode)
strReturn = Server.UrlEncode(strReturn)

strReturn = strReturn.Replace("-", "dash").Replace("+", "-")

strReturn = strReturn.Replace("%26", "and").
                    Replace("%2f", "or").
                    Replace("!", "excl").
                    Replace("*", "star").
                    Replace("%27", "apos").
                    Replace("(", "lprn").
                    Replace(")", "rprn").
                    Replace("%3b", "semi").
                    Replace("%3a", "coln").
                    Replace("%40", "at").
                    Replace("%3d", "eq").
                    Replace("%2b", "plus").
                    Replace("%24", "dols").
                    Replace("%25", "pct").
                    Replace("%2c", "coma").
                    Replace("%3f", "query").
                    Replace("%23", "hash").
                    Replace("%5b", "lbrk").
                    Replace("%5d", "rbrk").
                    Replace(".", "dot").
                    Replace("%3e", "gt").
                    Replace("%3c", "lt")

Return strReturn
于 2010-11-02T19:42:57.783 回答
0

我猜你正在寻找HttpUtility.UrlEncodeHttpUtility.HtmlDecode

string url = "http://www.google.com/search?q=" + HttpUtility.UrlEncode("Example");
于 2011-12-16T08:39:34.610 回答