以编程方式向用户授予特定表权限的最佳方法?
Posted
技术标签:
【中文标题】以编程方式向用户授予特定表权限的最佳方法?【英文标题】:Best approach to give specific tables permissions programmatically to users? 【发布时间】:2017-05-31 14:14:24 【问题描述】:我们有一个现有的工作系统,我被要求更改当前向用户授予“权限”的逻辑。当前的逻辑不是很合适,就性能而言,它太慢了。
当前结构
目前,我们有 25 个表,还有更多,我们有 110 个系统用户。有些是管理员,有些是具有特定权限的简单用户。我们在我们的系统中使用 M-V-C 实体框架代码优先方法。
对于每个表,我们有 5 个类似这样的复选框,第一个复选框用于授予访问页面的权限,第二个用于创建数据,第三个用于读取数据,第四个用于更新数据,第五个用于删除数据。
问题
现在所有这些权限都在一个用户表中,因此用户表中总共有 125 列。 25 个表格 x 5 个复选框 = 125 列。
所以,当我们注册用户时,我们可以选择权限,例如user1
只能从国家表中读取国家记录,只能从城市表中添加或编辑城市,只能从宗教表中删除宗教。
另外,系统有125个不同的角色。例如CountryCreate
、CountryDelete
、CityCreate
、CityDelete
等等。
在用户注册过程中,系统根据选中的值将不同的角色关联到用户。因此,假设管理员想为用户提供 70 个权限,那么 70 个角色将与该特定用户相关联,并且由于用户众多,因此有数千个 UserRoles
。如果用户具有特定角色,则创建角色以检查视图,然后显示特定功能,例如国家创建,否则不显示。
应用程序大部分时间都停止工作。因为每个用户都有很多角色和复选框。
我是该项目的新手,第一个工作是更改权限逻辑。实现它的最佳方法是什么?
当前代码
if (model.countryRead == true)
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
userManager.AddToRole(user.Id, "countryRead");
所以,像这样我们有 125 个if statements
,它只用于注册。在编辑中,如果复选框为假,我们还有 else statements
从角色中删除。另外,我们在用户模型中有 125 个属性。
解决这个问题的最佳方法是什么?
【问题讨论】:
您处理权限的方式没有任何问题。事实上,这就是您应该处理权限的方式。如果您的应用程序崩溃或出现问题,那是一个单独的不相关问题。代码不好或效率低下,服务器没有足够的资源,您的数据库需要调整等等。您将环境塑造成您的架构,而不是相反。 所以你的意思是有 125 列和角色的表不是问题? 定义“问题”。在你不得不放弃你的方法并重新开始之前,你可以拥有一些神奇的事物。您正在构建一个应用程序来满足您的业务。无论需要做什么,都需要这样做。从理论上讲,SQL 表中有 125 列之类的东西并没有固有的问题。这不像 SQL Server 会说“不,我只支持 124。现在你该干杯了。”如果存在性能问题或其他问题,您可以通过添加更多资源等其他方式解决这些问题。 不过,我要说的是,如果您将每个角色中的用户成员身份存储为某个表中的一列,那是错误的方法。是否选中表单中的复选框应取决于用户现有的角色成员资格,而不是某些表中的某些标志。您实际上是通过存储实际的复选框值来对数据进行非规范化。根据所有角色的列表构建您的复选框列表,然后根据用户是否实际担任该角色来选中该框。 【参考方案1】:你可以按照这个方法:
您已经拥有User
和Role
模型。你只需要另一个具有这种结构的模型:
public enum Actions
Insert,
Delete,
Update,
GetOne,
GetAll
public enum Services
Country,
Category,
Product,
Warehouse
public class UserAccess
public int Id get; set;
public ApplicationRole Role get; set;
public string Title get; set;
public Actions Action get; set;
public Services Service get; set;
使用此模型,您可以定义无限访问。
Users
有Roles
每个Role
可以有很多UserAccess
。
之后,你必须像125 if statements
一样手动检查它或者做一个更好的方法,如果你使用Web API,我建议你:
首先,您必须从 AuthorizeAttribute
类继承并使用您的访问模型(例如 Users
、Roles
和 UserAccesses
)对其进行自定义,并且您还必须覆盖 OnAuthorization
方法,例如:
public class ServiceAuthorize : AuthorizeAttribute
public ServiceAuthorize(Actions action, params Services[] services)
this.action = action;
this.services = services.ToList();
private Actions action get; set;
private List<Services> services get; set;
public override void OnAuthorization(HttpActionContext actionContext)
// check the user's roles here
// if the user don't have needed role or access you can reject it with this code
if (Unauthorized)
actionContext.Response = actionContext.Request.CreateResponse(
HttpStatusCode.Unauthorized,
new Dictionary<string, string>
HttpStatusCode.Unauthorized.ToString(), ((int)HttpStatusCode.Unauthorized).ToString()
);
那么,您必须在您的 Web API 中像这样使用Controllers
或Actions
上方的这个属性:
public class CountryController : ApiController
[ServiceAuthorize(new List<Actions>() Actions.GetAll , new List<Services>() Services.Country )]
public string GetCountries()
[ServiceAuthorize(new List<Actions>() Actions.Insert , new List<Services>() Services.Country )]
public string AddCountry(Country country)
希望对你有所帮助。
【讨论】:
【参考方案2】:在不了解您的项目结构(或瓶颈实际在哪里)的情况下很难给出建议,但您至少可以做 5 件事来帮助解决性能问题:
-
不要使用 5 个
boolean
字段作为权限,而是使用单个按位int
字段,并将值转换为 UI 上的 5 个复选框。例如1=access;2=create;4=read;8=update;16=delete
,那么如果该字段的值为13,则用户将具有访问、读取和更新的权限(1+4+8=13)。
不清楚为什么每个表都有一列。为每个表设置一行会更有意义,然后您可以为权限设置一列。
同时拥有“复选框”和“角色”听起来有点矫枉过正。如果您的每个角色都是一个权限,您可以完全消除“权限”表。
您可以通过使用System.Runtime.Caching.MemoryCache
在内存中缓存权限(和/或角色)来显着提高性能。
确保您的角色/权限未保存在 cookie 中,因为这意味着 每个 HTTP 请求无论是页面、图像、CSS 文件等,都会往返发送 cookie,这可以翻译大量额外字节的网络流量。
权限表
不确定客户“想要桌子”的原因。也许他们想要数据(已经作为角色存在),这就是您解释它的方式。您的首选应该是消除数据重复并仅使用角色(因为角色很容易被 MVC 使用)。
如果不可能,那么这就是你可以做的事情
UserID | Table (string) | Permission (int)
---------------------------------------------------
1 | Table1 | 13
1 | Table2 | 17
2 | Table5 | 3
请记住,控制“权限”的是您的应用程序,而不是实际存储数据的方式。但是可维护的数据库只会将数据存储在一个地方,让应用程序处理如何使用、显示和更新数据。
【讨论】:
是的,我也在考虑使用 int 而不是 bool。我第二次没看懂,一栏权限是什么意思?是的,我可以消除权限表,但客户需要该表。以上是关于以编程方式向用户授予特定表权限的最佳方法?的主要内容,如果未能解决你的问题,请参考以下文章