ASP.NET MVC阻止用户使用直接URL

时间:2016-05-26 17:02:03

标签: asp.net-mvc razor

所以我创造了一个简单的'#hello world"在MVC中作为概念的证明。索引视图列出了一些记录,其后是典型的"编辑","详细信息"和"删除" ActionLinks。

但是,根据哪个AD小组拥有该记录,我不会提供其中一些选项。例如,假设我提取了5条记录,而我是Group \ Role的成员,只拥有其中的1条记录。我的索引页面看起来像......

名称价格
  Foo1 $ 10.00详细信息
  Foo2 $ 20.00详细信息
  Foo3 $ 30.00详细信息|编辑|删除
  Foo4 $ 40.00详细信息
  Foo5 $ 50.00详细信息
  Foo6 $ 60.00详细信息

这一切都很棒。问题是,作为用户,我只需键入/ Home / Edit / Foo1的URL,它就可以编辑访问我不拥有的记录。

在第一次搜索时,我似乎应该实现一个叫做ChildActionOnly属性的东西。根据我的阅读,听起来好像我的控制器设置为..

[ChildActionOnly]
public ActionResult Edit(string id)
{
    return View(GetItem(id));
}

然后它不允许我改变我的网址并到达那里。但是,当我添加该属性时,Action Link也不再有效。

@Html.ActionLink("Edit", "Edit", new { id = item.FooName })

我知道我只是遗漏了一些东西。我已经实现了身份验证,所以除非你属于正确的角色,否则它已经阻止了对该控制器的所有访问。但是,一旦您有权访问......它并不意味着您可以更改任何内容。

5 个答案:

答案 0 :(得分:2)

无法阻止用户尝试访问任何网址。客户端(浏览器)仅提出请求。服务器有责任确定它是否应该返回。

隐藏URL以防止访问是所谓的“默默无闻”,它基本上与完全没有安全性相同。没有什么比这更模糊,持久的用户无法弄明白。您需要真正的安全性,例如与帐户身份验证相关的角色或对象级权限。

对于记录,您正在查看对象级权限。最基本的实现涉及在对象上创建表示该对象“所有权”的对象的外键。然后,在检索对象时,另外检查当前登录的用户是否为“所有者”,如果不是,则拒绝访问。

public ActionResult Edit(int id)
{
    var foo = db.Foos.Where(m => m.Id == id && m.OwnerId == User.Identity.GetUserId());
    if (foo == null)
    {
        return new HttpNotFoundResult();
    }

    // do whatever for authorized user
}

答案 1 :(得分:0)

根据文件:

<强> ChildActionOnlyAttribute Class

表示一个属性,用于指示仅应将操作方法​​作为子操作调用。

  

子操作方法为视图的一部分呈现内联HTML标记   而不是渲染整个视图。

     

可以调用任何标有ChildActionOnlyAttribute的方法   仅限操作 RenderAction HTML扩展方法。

     

有关使用属性的更多信息,请参阅。

答案 2 :(得分:0)

Nkosi对他的回答是正确的。要限制对此项的访问,您必须在Edit操作中执行用户验证。例如:

public ActionResult Edit(string id)
{
    var user = UserManager.FindById(User.Identity.GetUserId());
    //Check if user can access item
}

答案 3 :(得分:0)

要获得更灵活的方法,您可以为Controller操作方法创建自定义AuthorizeAttribute,然后将其设置为:

[MyAuthorize]    
public ActionResult Edit(string id)
{
    var user = UserManager.FindById(User.Identity.GetUserId());
    //Check if user can access item
}

然后使用'AuthorizeAttribute`的扩展版本,您可以在那里进行检查:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    // could be used to set the AD group that you are checking for
    // i.e. [MyAuthorize(strSecurityGroup="domain\group")] in the controller
    public string strSecurityGroup { get; set; }
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            return false;
        }
        var rd = httpContext.Request.RequestContext.RouteData;
        var id = rd.Values["id"];
        var userName = httpContext.User.Identity.Name;
        //Access the current record through a DataHandler class
        DataHandler dh = new DataHandler();
        // Gets a field from the database that holds the username for the owner of the record
        string createdBy = dh.GetCreatedBy(int.Parse(id.ToString()));
        bool isAuthorized = false;
        if (userName.ToString() == createdBy) isAuthorized = true;
        var User = System.Web.HttpContext.Current.User;
        if (User.IsInRole(@"domain\group")) isAuthorized = true;
        return isAuthorized;
    }
}

这就是我喜欢对AD进行授权的方式。您可以在AuthroizeAttribute中创建一个类属性,以便您也可以为每次使用该属性单独设置用户组。如果您使用授权机制来控制整个站点的操作,我认为这比每次手动执行授权检查更清晰。

答案 4 :(得分:0)

首先为过滤器创建一个类: 我们必须在操作过滤器的 OnActionExecuting 下调用此功能。

using System;
using System.Web.Mvc;
using System.Web.Routing;

namespace Customer.Filters
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class PreventFromUrl : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.HttpContext.Request.UrlReferrer == null ||
 filterContext.HttpContext.Request.Url.Host != filterContext.HttpContext.Request.UrlReferrer.Host)
           {
            filterContext.Result = new RedirectToRouteResult(new
                                      RouteValueDictionary(new { controller = "Dashboard", action = "Index", area = "" }));
           }
    }
}
}

然后将[PreventFromUrl]属性添加到操作或控制器的顶部:

 [PreventFromUrl]
 public ActionResult Index()
 {

 }