我正在创建一个具有用户概念的asp.net mvc应用程序.每个用户都可以编辑自己的个人资料.例如:
PersonID = 1可以通过转到http:// localhost/person/edit/1来编辑其个人资料
PersonID = 2可以通过转到http:// localhost/person/edit/2来编辑他们的个人资料
没有什么特别令人兴奋的......
但是,我在授权方案中遇到了一些麻烦.现在系统中只有两个角色,"管理员"和"默认用户",但将来可能会有更多.
我无法使用常规Authorize属性来指定授权,因为两个用户都处于相同的角色(即"DefaultUser").
所以,如果我像这样指定授权过滤器:
[Authorize(Roles = "DefaultUser")]
那就没有效果了.PersonID = 1可以进入并编辑自己的配置文件(因为它们应该可以),但是他们也可以将URL更改为http:// localhost/person/edit/2,并且他们具有编辑PersonID = 2的完全访问权限.配置文件(他们不应该这样做).
这是否意味着我必须创建自己的授权过滤器,在允许用户访问之前检查用户请求的操作是否"属于"他们?也就是说,如果当前登录的人正在请求参数= 1的编辑操作,是否需要进行自定义检查以确保当前登录的人员是PersonID = 1,如果是,则授权他们,如果没有,拒绝访问?
感觉我在这里遗漏了一些明显的东西,所以任何指导都会受到赞赏.
也许您可以组织控制器操作,使URL更像http:// localhost/person/editme,并显示当前登录用户的编辑表单.这样,用户就无法破解URL来编辑其他人.
我的$ .02:
授权和验证是两回事.简单地说,问题是你可以做这件事你应该这样做吗?你可以挑选你的朋友,你可以抠鼻子,但你不能挑选你的朋友鼻子!如果每个角色都可以做到(用户有手和鼻子),则无需检查授权.有一个Post方法供用户访问他们自己的个人资料并测试个人资料ID与表单的隐藏值或重定向(不是你的鼻子,走开).
有一个Get方法来编辑其他人的个人资料,并在这里检查管理员角色 - (我是一名医生,我有权将事情贴在你的鼻子上)......
更优雅的解决方案是编写自己的授权操作过滤器,方法是扩展[授权]或实现IAuthorizationFilter,如下所示:
public class AuthorizeOwnerAttribute: FilterAttribute, IAuthorizationFilter { #region IAuthorizationFilter Members public void OnAuthorization(AuthorizationContext filterContext) { // add logic here that compares the currently logged in user, to the owner of the profile that is being edited // get currently logged in user info from filterContext.HttpContext.User.Identity; // get profile being edited from filterContext.RouteData or filterContext.Something } #endregion }
我不确定OnAuthorization方法的实际逻辑是什么,但我的评论应该给你一个起点.您需要Google了解更多信息 - 如何将用户重定向到其他视图,或者是否抛出在其他地方处理的强类型异常(可能在[HandleError]属性中).
马特是对的.
授权的目的是表明他们被允许执行该功能 - 您要做的是说他们是否可以执行该特定ID的功能.
两个解决方案:
像Matt所说,做一个不带ID的动作,但从会话信息中查找当前登录的用户,然后检索它们.
制作一个带ID的操作,但只允许管理员访问 - 这样他们就可以根据需要修改其他用户信息.
但要回答这个问题,授权只是说"是的,这个人可以使用修改用户操作",而不是基于输入的参数.
另一种方法是你可以检查用户检索==当前用户,或者重定向到另一个动作,说他们无法编辑该用户 - 但最好只提供一个不采取行动的动作id,只获取当前登录用户.