自定义属性+使用查询字符串验证权限?

时间:2011-10-14 08:47:36

标签: asp.net-mvc-2 c#-3.0 query-string ninject custom-attributes

我的网站的某个部分会检查登录用户是否可以访问记录的ID(报告ID),如果是这样,他们可以查看该页面上的内容。可以有各种不同类型的用户/公司来查看内容。

编写自定义属性以检查用户是否可以访问ID的最佳做法是什么?我应该传入查询字符串吗?请注意,id将来自route / url。

E.g。报告ID = 678。 网址:

  • / Report / 678 / Detail
  • /报表/ 678 /进展/分步
  • /报表/ 678 /任务管理/ 78 /
  • /报表/ 678 /参与者

使用下面的代码

[ReportAuthorizationAttribute ())] //get query string yourself
[ReportAuthorizationAttribute (Request.Querystring["reportid"))] //this does not look possible to do???

//将添加到此区域的基本控制器的代码

public class ReportAuthorizationAttribute : AuthorizeAttribute
{

    /// <summary>
    /// inject via Ninject - there must be a better way? Using service locator?
    /// </summary>
    [Inject]
    public readonly IReportRepo _repo { get; set; }
    [Inject]
    public readonly IUserSession _user { get; set; }

    private int _reportid;

    public ReportAuthorizationAttribute()
        : base()
    { //*Is this way the best way?*
     _reportid= Int32.Parse(HttpContext.Current.Request.QueryString["reportid"]);
    }

    public ReportAuthorizationAttribute(params int reportid)
        : base()
    {
        _reportid = reportid;
    }

    public ReportAuthorizationAttribute(params string reportid)
        : base()
    {
        _reportid= Int32.Parse(reportid);
    }


    public bool AlwaysAllowLocalRequests = false;


    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {

        if (httpContext == null)
            throw new NoAccessException("httpContext is null");

        if (!httpContext.User.Identity.IsAuthenticated)
            throw new NoAccessException("unauthorized user");

        var companyid = _user.GetCurrentUser().CompanyID;
        if (AlwaysAllowLocalRequests && _repo.IsCompanyParticipantInReport(_reportid, companyid))
            return true;

        return false;
    }


}

1 个答案:

答案 0 :(得分:2)

  

// 这是最好的方法吗?

     

_reportid= Int32.Parse(HttpContext.Current.Request.QueryString["reportid"]);

如果您使用路由,reportid将不会成为查询字符串的一部分。您需要从路线中获取它:

var reportId = filterContext.RequestContext.RouteData.Values["reportId"];

也不要在动作过滤器构造函数中使用HttpContext.Current。仅在AuthorizeCore方法中使用它:

public class ReportAuthorizationAttribute : AuthorizeAttribute
{
    [Inject]
    public readonly IReportRepo _repo { get; set; }

    [Inject]
    public readonly IUserSession _user { get; set; }

    public bool AlwaysAllowLocalRequests = false;

    private string _reportId;

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        _reportId = filterContext.RequestContext.RouteData.Values["reportId"] as string;
        base.OnAuthorization(filterContext);
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
            return false;

        if (!httpContext.User.Identity.IsAuthenticated)
            return false;

        int reportId;
        if (!int.TryParse(_reportId, out reportId))
            return false;

        var companyid = _user.GetCurrentUser().CompanyID;
        return AlwaysAllowLocalRequests && 
               _repo.IsCompanyParticipantInReport(reportId, companyid));
    }
}