如何用asp.net MVC4隐藏URL中的ID

how can i hide ID in URL with asp.net MVC4

我的网址

http://www.domain.com/Products/{Alias}-{ID}

和我的路线

1
2
3
4
5
routes.MapRoute(
               name:"ProductDetail",
               url:"Products/{Alias}-{detailId}",
               defaults: new { controller ="Products", action ="ProductDetail", id = UrlParameter.Optional }
            );

在控制器中

1
2
3
4
5
6
7
8
9
public ActionResult ProductDetail(int? detailId)
        {
            var pro = db.Products.Find(detailId);
            if (pro == null)
            {
                return RedirectToAction("Index","NotFound");
            }
            return View(pro);
        }

现在,我想在我的网址中隐藏ID

http://www.domain.com/Products/{Alias}

我怎样才能做到这一点


简答

你不可能做你想做的事。如果您希望能够从控制器访问detailId,则必须将detailId作为URL的一部分传递 - 您无法访问不存在的内容。

答案很长

还有其他方法来解决用户隐藏detailId的问题,以下是一些建议:

1.改用Alias:

您可以一起删除detailId并使用Alias值。但是,这将要求Alias值对您尝试查询的产品是唯一的,并且所需的更改可能如下所示:

1
2
3
4
5
6
7
8
9
10
11
routes.MapRoute(
    //..
    url:"Products/{Alias}",
    //..
);

public ActionResult ProductDetail(string Alias)
{
    var pro = db.Products.FindByAlias(Alias);
    //...
}

2.使用POST请求:

另一个有效隐藏URL中的detailId但仍然允许将值传递给控制器??的解决方案是使用POST请求,其中参数值将在POST请求体中指定。

然而,这样做的缺点是您不能简单地为用户提供点击的URL,并且您站点内的编码链接需要花费更多的精力。通常使用MVC,POST请求在提交表单时发生,您也可以使用javascript ajax调用执行POST请求。

在这个答案中有点太多了,所以如果你有兴趣那么做一些研究,比如这个问题,或者这里的一些信息。

3.加密detailId值:

现在这个选项不会隐藏URL中的detailId,但如果您担心的是当前ID太用户友好,那么您可以'加密'(松散地使用)该值。例如,您可以转换为base64字符串,然后返回到控制器中的int。这会给你一个像这样的URL:

1
http://www.domain.com/Products/{Alias}-MQ%3D%3D

此URL将1表示为detailId,如果使用此方法,则必须确保对您的值进行URL编码/解码。

在这种情况下,Base64转换并不是真正"加密"它,任何半精明的用户都会注意到这一点,并且可以绕过它。但是,如果您想采用这种方法,只有服务器知道加密/解密密钥,您就可以轻松使用更安全的双向加密算法。这里的缺点是只有服务器才能为用户生成有效的URL以"点击"。

在这一点上,值得考虑的是,如果你担心的是,通过包含一个简单的数字ID,URL太用户友好,那么问题是:你为什么关心?

如果您担心用户可以简单地更改detailId值,然后可以访问他们应该有权访问的产品,那么您在安全性方面会遇到更大的问题。如果是这种情况,那么您的控制器应负责任地验证用户是否可以访问他们尝试访问的产品,然后采取相应措施。

所有安全检查和验证都应该在服务器端处理,永远不要依赖客户端代码或用户操作来为您完成。