MVC 5 FileContentResult 操作结果权限和重定向
MVC 5 FileContentResult Action Result Permission and Redirect
我有一个 MVC 5 应用程序,允许用户下载存储在数据库中的文件。我正在使用 FileContentResult 操作方法来执行此操作。
我可以在整个应用程序中限制对此方法的访问,但聪明的用户可以弄清楚操作 URL 并粘贴类似这样的内容 (localhost:50000/Home/FileDownload?id=13)进入他们的浏览器,只需更改参数即可下载任何文件。
我想限制用户这样做。只允许管理员角色和具有只能由数据库调用确定的特定权限的用户下载文件。
我正在寻找的是,如果用户使用 URL 下载文件但没有适当的权限,我想通过消息重定向用户。
我想执行类似于下面的代码或类似的操作,但出现以下错误:无法将类型 'System.Web.Mvc.RedirectToRouteResult' 隐式转换为 'System.Web.Mvc.FileContentResult'
我知道我不能在这里使用 return RedirectToAction("Index"),只是寻找一些关于如何处理这个问题的想法。
public FileContentResult FileDownload(int id)
{
//Check user has file download permission
bool UserHasPermission = Convert.ToInt32(context.CheckUserHasFileDownloadPermission(id)) == 0 ? false : true;
if (User.IsInRole("Administrator") || UserHasPermission)
{
//declare byte array to get file content from database and string to store file name
byte[] fileData;
string fileName;
//create object of LINQ to SQL class
//using LINQ expression to get record from database for given id value
var record = from p in context.UploadedFiles
where p.Id == id
select p;
//only one record will be returned from database as expression uses condtion on primary field
//so get first record from returned values and retrive file content (binary) and filename
fileData = (byte[])record.First().FileData.ToArray();
fileName = record.First().FileName;
//return file and provide byte file content and file name
return File(fileData, "text", fileName);
}
else
{
TempData["Message"] = "Record not found";
return RedirectToAction("Index");
}
}
由于 FileContentResult
和 RedirectToRouteResult
都是从 ActionResult
继承而来的,只需使用 ActionResult
而不是 FileContentResult
作为您操作的 return 类型:
public ActionResult FileDownload(int id)
{
if(IsUserCanDownloadFile()) // your logic here
{
// fetch the file
return File(fileData, "text", fileName);
}
return RedirectToAction("Index");
}
或者如果您更喜欢属性,您可以编写自己的授权属性来检查权限:
public class FileAccessAttribute : AuthorizeAttribute
{
private string _keyName;
public FileAccessAttribute (string keyName)
{
_keyName = keyName;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// imagine you have a service which could check the Permission
return base.AuthorizeCore(httpContext)
|| (this.ContainsKey
&& _permissionService.CanDownload(httpContext.User.Identity.GetUserId(),
int.Parse(this.KeyValue.ToString()));
}
private bool ContainsKey
{
get
{
// for simplicity I just check route data
// in real world you might need to check query string too
return ((MvcHandler)HttpContext.Current.Handler).RequestContext
.RouteData.Values.ContainsKey(_keyName);
}
}
private object KeyValue
{
get
{
return ((MvcHandler)HttpContext.Current.Handler)
.RequestContext.RouteData.Values[_keyName];
}
}
}
现在您可以在您的操作上装饰自定义属性:
[FileAccess("id", Roles ="Administrator")]
public FileContentResult FileDownload(int id)
{
// fetch the file
return File(fileData, "text", fileName);
}
我有一个 MVC 5 应用程序,允许用户下载存储在数据库中的文件。我正在使用 FileContentResult 操作方法来执行此操作。
我可以在整个应用程序中限制对此方法的访问,但聪明的用户可以弄清楚操作 URL 并粘贴类似这样的内容 (localhost:50000/Home/FileDownload?id=13)进入他们的浏览器,只需更改参数即可下载任何文件。
我想限制用户这样做。只允许管理员角色和具有只能由数据库调用确定的特定权限的用户下载文件。
我正在寻找的是,如果用户使用 URL 下载文件但没有适当的权限,我想通过消息重定向用户。
我想执行类似于下面的代码或类似的操作,但出现以下错误:无法将类型 'System.Web.Mvc.RedirectToRouteResult' 隐式转换为 'System.Web.Mvc.FileContentResult'
我知道我不能在这里使用 return RedirectToAction("Index"),只是寻找一些关于如何处理这个问题的想法。
public FileContentResult FileDownload(int id)
{
//Check user has file download permission
bool UserHasPermission = Convert.ToInt32(context.CheckUserHasFileDownloadPermission(id)) == 0 ? false : true;
if (User.IsInRole("Administrator") || UserHasPermission)
{
//declare byte array to get file content from database and string to store file name
byte[] fileData;
string fileName;
//create object of LINQ to SQL class
//using LINQ expression to get record from database for given id value
var record = from p in context.UploadedFiles
where p.Id == id
select p;
//only one record will be returned from database as expression uses condtion on primary field
//so get first record from returned values and retrive file content (binary) and filename
fileData = (byte[])record.First().FileData.ToArray();
fileName = record.First().FileName;
//return file and provide byte file content and file name
return File(fileData, "text", fileName);
}
else
{
TempData["Message"] = "Record not found";
return RedirectToAction("Index");
}
}
由于 FileContentResult
和 RedirectToRouteResult
都是从 ActionResult
继承而来的,只需使用 ActionResult
而不是 FileContentResult
作为您操作的 return 类型:
public ActionResult FileDownload(int id)
{
if(IsUserCanDownloadFile()) // your logic here
{
// fetch the file
return File(fileData, "text", fileName);
}
return RedirectToAction("Index");
}
或者如果您更喜欢属性,您可以编写自己的授权属性来检查权限:
public class FileAccessAttribute : AuthorizeAttribute
{
private string _keyName;
public FileAccessAttribute (string keyName)
{
_keyName = keyName;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// imagine you have a service which could check the Permission
return base.AuthorizeCore(httpContext)
|| (this.ContainsKey
&& _permissionService.CanDownload(httpContext.User.Identity.GetUserId(),
int.Parse(this.KeyValue.ToString()));
}
private bool ContainsKey
{
get
{
// for simplicity I just check route data
// in real world you might need to check query string too
return ((MvcHandler)HttpContext.Current.Handler).RequestContext
.RouteData.Values.ContainsKey(_keyName);
}
}
private object KeyValue
{
get
{
return ((MvcHandler)HttpContext.Current.Handler)
.RequestContext.RouteData.Values[_keyName];
}
}
}
现在您可以在您的操作上装饰自定义属性:
[FileAccess("id", Roles ="Administrator")]
public FileContentResult FileDownload(int id)
{
// fetch the file
return File(fileData, "text", fileName);
}