我想听听是否有人发现我在这个基于Oracle的MVC.NET应用程序中实现安全性的任何问题,无论是安全问题,并发问题还是可伸缩性问题。
首先,我实施了 CustomOracleMembershipProvider 来处理会员商店的数据库界面。
我实现了一个名为 User 的自定义Principal,它实现了IPrincipal,并且它有一个Roles哈希表。
我还创建了一个名为 AuthCache 的单独类,它具有用户对象的简单缓存。其目的很简单,避免返回数据库,同时将缓存与Web层或数据层分离。 (所以我可以在MVC.NET,WCF等之间共享缓存)
MVC.NET股票 MembershipService 使用CustomOracleMembershipProvider(在web.config中配置), MembershipService 和 FormsService 共享访问权限singleton AuthCache。
我的AccountController.LogOn()方法:
1)通过MembershipService验证用户。验证()方法,还将角色加载到User.Roles容器中,然后将用户缓存在AuthCache中。
2)通过FormsService将用户签名到Web上下文。 SignIn()访问AuthCache(不是数据库)以获取用户,设置 HttpContext.Current.User 到缓存的用户主体。
在global.asax.cs中, Application_AuthenticateRequest()已实施。它解密FormsAuthenticationTicket,通过ticket.Name(用户名)访问AuthCache,并通过从AuthCache设置 Context.User = user来设置Principal。
简而言之,所有这些类共享AuthCache,并且我在缓存存储方法中为线程同步提供了 lock()。读取方法没有锁定。
自定义成员资格提供程序不知道缓存,MembershipService不知道任何HttpContext(因此可以在Web应用程序之外使用),并且FormsService除了访问AuthCache之外不使用任何自定义方法为初始登录设置Context.User,因此它不依赖于特定的成员资格提供程序。
我现在看到的主要事情是,如果用户从多个会话登录,AuthCache将共享一个User对象。所以我可能不得不将密钥从UserId改为其他东西(也许在FormsAuthenticationTicket中使用密钥?)。
答案 0 :(得分:3)
为什么要为角色使用Hashtable?除非您希望人们拥有多个角色,否则普通列表的搜索速度可能会更快。如果您可以提前预测所有角色,那么使用位掩码/标志枚举会更好。
你应该尽量避免编写自己的锁定机制,因为它很容易出错。使用新的System.Collections.Concurrent类,或者如果你必须自己滚动,那么一定要使用Interlocked(因为所有其他锁定机制都非常昂贵)。
缓存应该使用WeakReference封装来允许条目进行GCed,并且如果缺少条目,则支持从数据库中检索用户信息。如果你需要分布式缓存,也许可以看一下Velocity。
共享用户对象可能不是问题,但可能不是推荐的策略。许多数据库访问框架将跟踪在会话或工作单元中检索的对象,并且跨会话共享对象将是有问题的。如果您确实要共享用户对象,请确保使它们不可变。
最后,我个人鄙视整个会员提供程序API,因为它使用GUID进行身份识别,而用户配置文件的默认SQL Server数据库设计非常糟糕(又称性能杀手)。这对你来说似乎不是一个问题,因为你已经推出了自己的(数据库和实现),但是你可能想要评估实现API是否有任何实际好处,或者它是否主要是以特定方式将你绑在一起的束缚做事。