如果我有一个不经常(每月一次)更改的MySQL表,其中包含诸如web服务的活跃用户帐户之类的信息。这样做的安全性如何:
public AccountDao
{
List<Account> accounts;
/*fields*/
public AccountDao()
{
refreshAccounts();
}
public void refreshAccounts()
{
this.accounts = /*call to database to get list of accounts*/
}
public boolean isActiveAccount(String accountId)
{
//logic involving in memory list object above
}
}
我会这样做,因为我必须检查用户是否有一个活动帐户,以允许访问web服务的每个请求。这将允许我避免在每个请求上对数据库层(目前强调)进行一次SQL调用。我的问题是,在生产环境中存储这样的数据有多安全?
顺便说一下,每当通过API调用添加新用户帐户时,我都会刷新帐户列表。如上所述,这种情况大约每月发生一到两次。
- 访问DAO中的共享状态(以及潜在的调用者)需要以某种方式同步,以实现线程安全。
- 陈旧的数据可能导致错误的访问决策。因为这可能与安全性相关,所以您的代码需要是防弹的;特别是,它需要在故障情况下可靠地工作。这使得任何基于通知的方案都不稳定——如果通知丢失了怎么办?
- 凭证在内存中的生存期被延长。机密性仍然可以通过对凭证进行散列来实现(坦率地说,如果有人可以读取应用程序的内存,那么您就会遇到许多其他问题)。在内存中操作密码需要攻击者能够访问堆内存,如果他可以这样做,那么无论如何你都失去了,因为他可以很容易地更改用于读取帐户的数据库连接。
也就是说,对于一个高流量的web服务,缓存凭据听起来是一个明智的想法,但它并不是完全微不足道的。
编辑:不,web容器不同步线程。并发请求将由并发线程提供服务,如果这些线程读取和写入相同的数据,则可能导致数据竞争。例如,一个线程可以在使用新信息更新时读取帐户列表,因此看到的是一个不完整的列表。当相应的数据库表发生变化时,如果您有某种类型的触发器来更新内存中的对象,那么它应该是安全的。
如果没有触发器,它就变成了正确性和潜在的策略问题。如果基础架构的不同部分有不同的内存数据库版本,会发生什么情况?例如,在添加或删除用户和您的服务反映该更改之间的间隔时间是多长是可接受的?
看看缓存。您的库可能已经支持它了,如果不支持的话,memcached是一个不错的选择。