Model view controller MVC 3页导航安全规则
我有一个遵循PRG模式的MVC3应用程序,我正在寻找一种为我的应用程序定义导航规则的最佳方法。例如,我有一个页面A、B、C和D的应用程序。假设A是一个登录页面。用户成功登录后,用户将被重定向到B页。现在我不想让用户在地址栏中键入C页的url并访问C页(只有在发布B页或从D页返回按钮后才能访问C页),我还必须为所有其他页设置类似的规则(假设用户在D页时,不应允许他们进入B页) 目前,我有一个选项,可以检查@Request.UrlRefferer属性以获取每个请求的源,并决定重定向到哪个页面。我不确定这是否是最佳解决方案Model view controller MVC 3页导航安全规则,model-view-controller,asp.net-mvc-3,Model View Controller,Asp.net Mvc 3,我有一个遵循PRG模式的MVC3应用程序,我正在寻找一种为我的应用程序定义导航规则的最佳方法。例如,我有一个页面A、B、C和D的应用程序。假设A是一个登录页面。用户成功登录后,用户将被重定向到B页。现在我不想让用户在地址栏中键入C页的url并访问C页(只有在发布B页或从D页返回按钮后才能访问C页),我还必须为所有其他页设置类似的规则(假设用户在D页时,不应允许他们进入B页) 目前,我有一个选项,可以检查@Request.UrlRefferer属性以获取每个请求的源,并决定重定向到哪个页面。我不确
感谢您的反馈!!不要将您的安全性建立在这个基础上。使用[Authorize]属性定义安全性。URLreferer也很容易伪造
你为什么要限制这一点?如果你有一个商业原因,用户最多会经历一个特定的流程,然后考虑cookie、session或数据库条目来记录他们当前的“完成”状态-伊江有一些持久的方法来确定这一点。ch页面。如果令牌存在并且与用户的当前会话匹配,则为其加载页面。当然,如果用户理解这一点,这可能是伪造的-但如果您只是试图确保正确的流,那么这也是一种方法。用户在点击上一步之前不会获得包含当前会话id的链接。
如果是您不希望通过URL访问特定页面,可用的一个选项是确保无法通过URL访问该页面。要访问该页面,请执行将返回视图而不是重定向的POST操作。这意味着您的POST操作返回的视图将显示在具有上一页URL的页面上。例如ple: 页面A的URL是/login
,登录后,用户被重定向到页面B。URL现在是/home
。页面B发送POST请求,页面内容变为页面C,但URL仍然保持为/home
。查看页面C内容的唯一方法是访问页面B并发送POST请求
这打破了PRG模式,但这是一种选择
还有另一种选择,存储用户的当前权限,指示允许用户进入的页面,并在执行操作之前检查用户是否有权查看页面。您可以将代码放置在ActionAttribute
中,您可以将其应用于您的操作方法或整个控制器。如果您想要更多关于这项技术的详细解释,请给我留言,我将写下另一个更详细描述这项技术的答案
下面是上述技术概念的快速证明:
public class PermissionsNeeded : ActionFilterAttribute
{
string expectedPermission;
public PermissionsNeeded(string permission)
{
expectedPermission = permission;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var currentPermissions = filterContext.HttpContext.Session["CurrentPermissions"] as IEnumerable<string> ?? new List<string>();
// If user does NOT have permission to access the action method
if(!currentPermissions.Contains(expectedPermission)
{
throw new HttpException(403, "User is not authorized to view this page");
}
}
}
class YourController : Controller
{
[HttpPost]
public ActionResult PageB()
{
var currentPermissions = Session["CurrentPermissions"] ?? new List<string>();
currentPermissions.Add("PostedFromPageB");
Session["CurrentPermissions"] = currentPermissions;
return RedirectToAction("PageC");
}
[PermissionsNeeded("PostedFromPageB")
public ActionResult PageC()
{
return View();
}
}
需要公共类权限:ActionFilterAttribute
{
字符串expectedPermission;
需要公共权限(字符串权限)
{
expectedPermission=许可;
}
公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext)
{
var currentppermissions=filterContext.HttpContext.Session[“currentppermissions”]作为IEnumerable??new List();
//如果用户没有访问操作方法的权限
如果(!currentPermissions.Contains)(expectedPermission)
{
抛出新的HttpException(403,“用户无权查看此页面”);
}
}
}
类控制器:控制器
{
[HttpPost]
公共行动结果第b页()
{
var currentPermissions=会话[“currentPermissions”]??新列表();
currentPermissions.Add(“PostedFromPageB”);
会话[“CurrentPermissions”]=CurrentPermissions;
返回重定向到操作(“PageC”);
}
[需要许可证(“PostedFromPageB”)
公共行动结果页面C()
{
返回视图();
}
}
当前,自定义属性一次只接受一个权限,这只是一个需要纠正的限制。当您觉得用户不应该再拥有某些权限时,您将负责删除会话中存储的权限。我抛出了一个HttpException,返回403状态代码(未经授权的访问)但是,如果您想返回一个ActionResult,例如
重定向路由
或视图
,则可以为filterContext.Result
属性设置一个值。我最终执行此任务,如下所示:
谢谢大家的回复!谢谢大家的回复。我不喜欢打破PRG模式。你能解释一下你的其他选择吗?@matmat:为我前面描述的替代方法添加了概念证明。可能需要一些更改以使其完全符合你的需要。如果你需要任何澄清,请告诉我。谢谢您的回答,尽管您的方法是一种选择,但我决定使用数据库,因为它有助于排除故障。请参考我下面的回答。感谢您的回答。是的,我正在尝试这样做,以确保正确的流程。我喜欢将完成状态存储在会话中,并在此基础上设置规则。但是,正如您所说如果URLRER和seesion id都可以伪造,那么想知道有没有最好的方法可以做到这一点?如果你不担心“手工篡改”,那么这两种方法都可以。