使用控制器限制网站访问

时间:2013-07-05 15:31:33

标签: c# asp.net-mvc

我目前正在开展一个简单的小项目。我有一个存储在数据库中的用户列表,如下所示:

Id (uniqueidentifier primary key), FirstName(varchar), LastName(varchar), PhoneNo(varchar), DomainAC(varchar)

我正在使用ASP.net MVC创建一个具有以下简单功能的页面:

http://img17.imageshack.us/img17/7285/difq.png

显示页面上的所有用户详细信息 - 我使用以下代码生成的代码,我使用连接到我的数据库的ModelController的Index函数创建的视图:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Proj.Models.Employee>>" %>

<!DOCTYPE html>

<html>
<head runat="server">
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <p>
        <%: Html.ActionLink("Create New", "Create") %>
    </p>
    <table>
        <tr>
            <th>
                <%: Html.DisplayNameFor(model => model.LastName) %>
            </th>
            <th>
                <%: Html.DisplayNameFor(model => model.PhoneNo) %>
            </th>
            <th>
                <%: Html.DisplayNameFor(model => model.DomainAC) %>
            </th>
            <th>
                <%: Html.DisplayNameFor(model => model.FirstName) %>
            </th>
            <th></th>
        </tr>

    <% foreach (var item in Model) { %>
        <tr>
            <td>
                <%: Html.DisplayFor(modelItem => item.LastName) %>
            </td>
            <td>
                <%: Html.DisplayFor(modelItem => item.PhoneNo) %>
            </td>
            <td>
                <%: Html.DisplayFor(modelItem => item.DomainAC) %>
            </td>
            <td>
                <%: Html.DisplayFor(modelItem => item.FirstName) %>
            </td>
            <td>
                <%: Html.ActionLink("Edit", "Edit", new { id=item.Id }) %> |
                <%: Html.ActionLink("Details", "Details", new { id=item.Id }) %> |
                <%: Html.ActionLink("Delete", "Delete", new { id=item.Id }) %>
            </td>
        </tr>
    <% } %>

    </table>
</body>
</html>

这会呈现一个裸HTML页面,显示裸表中的所有用户。有创建/编辑/删除按钮;但他们什么都不做。

我想做的只是,每行

if(DomainAC == currently logged in Domain AC || currently logged in Domain AC is admin)
    Allow user to edit/update details.

经过一些调查后,我想我需要创建一个自定义控制器来读取您当前登录的用户,并在DB返回的行==当前登录用户时显示编辑按钮。

    [Authorize(Users = @Context.User.Identity.Name)]
    public ActionResult CurrentUser()
    {
        ViewBag.Message = "You are the logged in user";

        return View();
    }

    [Authorize(Roles = @"DOMAIN\Administrators")]

    public ActionResult Admins()
    {
        ViewBag.Message = "Your are admin.";

        return View();
    }

2 个答案:

答案 0 :(得分:1)

您需要使用这样的自定义属性:

public class DomainACUserAttribute : AuthorizeAttribute
{
    private UnitOfWork _unitOfWork = new UnitOfWork();

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var isAuthorized = false;
        var username = httpContext.User.Identity.Name;
        // Some code to find the user in the database...
        var user = _unitOfWork.EmployeeRepository.Find(username);
        if(user != null)
        {
           isAuthorized = true;
        }


        return isAuthorized;
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {            
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        if (AuthorizeCore(filterContext.HttpContext))
        {
            SetCachePolicy(filterContext);
        }
        else
        {
           // If not authorized, open the Unauthorized page... 
           filterContext.Result = new ViewResult { ViewName = "Unauthorized" };
        }
    }

    protected void SetCachePolicy(AuthorizationContext filterContext)
    {
        // ** IMPORTANT **
        // Since we're performing authorization at the action level, 
        // the authorization code runs after the output caching module. 
        // In the worst case this could allow an authorized user 
        // to cause the page to be cached, then an unauthorized user would later 
        // be served the cached page. We work around this by telling proxies not to 
        // cache the sensitive page, then we hook our custom authorization code into 
        // the caching mechanism so that we have the final say on whether a page 
        // should be served from the cache.
        HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
        cachePolicy.SetProxyMaxAge(new TimeSpan(0));
        cachePolicy.AddValidationCallback(CacheValidationHandler, null /* data */);
    }

    public void CacheValidationHandler(HttpContext context,
                                        object data,
                                        ref HttpValidationStatus validationStatus)
    {
        validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
    }
}

然后,您可以将此属性用于您的控制器操作,如下所示:

[DomainACUser]
public ActionResults Edit()
{
  // Some code...
}

您只能为管理员创建单独的自定义属性。并且,将其用于仅由管理员访问的操作。

如果要隐藏不应该访问它们的人的编辑和删除链接,可以检查控制器中的用户权限,并将信息传递给ViewData中的View,如下所示:

// Code to check if the user is admin...
if (User is Admin)
{
   ViewData["DisplayEdit"] = true;
}

并且,在您的视图中:

<td>
    <% if ((bool)ViewData["DisplayEdit"]) { %>
        <%: Html.ActionLink("Edit", "Edit", new { id=item.Id }) %> 
    <% } %>
</td>

答案 1 :(得分:0)

我认为您最好的选择就是将条件直接放入您的视图中,并手动检查控制器的权限:

<td>
    <% if (User.IsInRole("Administrators") || User.Identity.Name == item.DomainAC) { %>
        <%: Html.ActionLink("Edit", "Edit", new { id=item.Id }) %> |
        <%: Html.ActionLink("Details", "Details", new { id=item.Id }) %> |
        <%: Html.ActionLink("Delete", "Delete", new { id=item.Id }) %>
    <% } %>
</td>

public ActionResult Edit(int id) {
    var user = GetUserById(id);
    if (!User.IsInRole("Administrators") && User.Identity.Name != user.DomainAC) {
        // unauthorized
    }

    // authorized - continue
}