I have a certain part of my site that checks if the logged on user can access the id of a record (Report id), if so they can view the content on that page. There can be various different types of users/companies that will view the content.
What is the best practise for writing a custom attribute that will check if user can access the id? Should I pass in a query string? Note that the id will come from the route/url.
E.g. Report id = 678. urls:
- /Report/678/Detail
- /Report/678/Progress/Staged
- /Report/678/TaskManager/78/
- /Report/678/Participants
usage of code below
[ReportAuthorizationAttribute ())] //get query string yourself
[ReportAuthorizationAttribute (Request.Querystring["reportid"))] //this does not look possible to do???
//Code that will be added to the base controller for this area
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)开发者_JAVA百科)
return true;
return false;
}
}
//Is this way the best way?
_reportid= Int32.Parse(HttpContext.Current.Request.QueryString["reportid"]);
If you use routing, reportid
won't be part of the query string. You need to fetch it from the route:
var reportId = filterContext.RequestContext.RouteData.Values["reportId"];
Also don't use HttpContext.Current in your action filter constructor. Use it only inside the AuthorizeCore
method:
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));
}
}
精彩评论