JPC*_*PCF -1 architecture database-design design-patterns software-design
关于如何设计参数表,我很怀疑...
谢谢!
注意:这个问题扩展了这一点.
没有看到一个例子,很难理解你所描述的内容.但听起来你在谈论一个通常被称为One True Lookup Table的数据库设计反模式.
CREATE TABLE Parameters (
key VARCHAR(20) PRIMARY KEY,
value VARCHAR(255) NOT NULL,
);
Run Code Online (Sandbox Code Playgroud)
这种设计的问题包括:
您不能使用最适合的SQL数据类型,因为该value列必须包含整数,日期,字符串 - 所有可能参数类型的所有值.
您不能使用约束来限制给定参数类型的值.例如,您可能需要一个CHECK约束来确保邮政编码符合某种模式.但你不能,因为那时所有类型的所有参数都必须符合相同的模式.
您不能将此表用作查找表来约束其他表.例如,如果您希望country另一个表中的列引用国家/地区列表而不允许其他值.通过将所有查找数据存储在同一列中,您的country列可以引用任何参数类型的任何值.没有国家'M'或者'F'您的数据库允许country引用它.
你不能创建一个真正的FOREIGN KEY约束,除非该Parameters.value列有一个UNIQUE约束,它不能,因为'M'可能是"男性"或"中等衬衫大小",因此在参数表中出现两次.
您无法保证给定的密钥完全存在,因为无法强制表包含具有某个主键的行.这是NOT NULL传统数据库设计中的内容,其中参数属于列而不是行.
表可能会变大,因此查找正确属于小集的值变得低效.您的应用程序配置参数列表与国家/地区和邮政编码等列表一起存储.
尽管理查德哈里森在回答你的另一个问题时写道,但他错了.OTLT是一个糟糕的设计,你会后悔使用它.
关于您的具体问题:
你认为让html包含网络应用程序的pks是一种不好的做法吗?我认为是,我建议使用guids代替pks.
关于在Web应用程序的用户可见层中显示pks的最常见警告是,它可以为攻击者提供有关如何处理数据部分的信息.听起来你仍然在你的网络应用程序中显示pk值,但你只需要交换整数的GUID.我不知道这有多好.
更新:要明确的是,如果您的代码允许用户通过了解PK值来执行非法操作,那么如果用户知道映射到PK值的某个代理值,它也会允许相同的非法操作.您尚未使用代理值添加任何保护.
那么有必要"冒风险"吗?可以做什么呢?
防守编程. 不要假设用户只会点击为他们提供的链接,他们可以编辑链接以指定其他pk值并提交.攻击者擅长此类事情.
例如:
http://www.example.com/change-password.php?account_id=12345&new-password=xyzzy
Run Code Online (Sandbox Code Playgroud)
您的PHP脚本应该检查当前用户的会话是否已登录到有权更改帐户12345密码的帐户.不要只是假设它没关系,因为Web应用程序不会向用户显示执行某些操作的链接他们没有特权.即使应用程序正确,攻击者也可以将值更改为他们想要的任何内容,然后提交.
您必须在应用程序中编写代码,以检查用户是否有权使用他们请求的数据,假设他们可以请求数据,即使他们没有权限查看数据.如果可以这样做,则可以降低暴露pk值的风险.
更新:隐藏PK值是默默无闻的安全措施,这不是一种有效的安全策略.您的代码需要检查用户是否有权查看或更改该PK的记录.如果您正确执行此操作,攻击者如果尝试执行不应该执行的操作,则应该收到"拒绝访问"错误.
如果您有程序员犯错误,那么构建您的应用程序以假定用户没有权限,并要求程序员编写代码以在每种类型的操作之前建立授权.
此外,使用代码测试来验证用户只有在具有正确权限时才能调用给定任务,并且非特权用户无法调用该任务,并且他们会收到相应的错误消息.要求程序员为他们触摸的任何功能编写测试.
我更喜欢只有一个带有所有参数的表和一个带有键的列来从上层引用它们.
不,OTLT是一个糟糕的设计.往上看.
您如何看待源文件与参数表具有相同的信息?我看到一些项目的源代码与每个与参数相关的pk ...这是一个好习惯吗?
不可以.在数据库中存储参数的关键在于您可以通过访问数据库来更新它们,它们将自动在使用该数据的其他页面中生效.如果必须更新代码以使用新值,那么将参数存储在数据库中没有任何好处.如果这是真的,您也可以仅将值存储在代码中.
关于带参数数据的源代码:如何从客户端代码中引用特定的prm?假设我在业务层中有一些关于性别的逻辑,它使用prm数据来工作......如何关联两个数据(我用来创建常量表)?我想我至少需要一个在BL上硬编码的密钥......
我猜你用一个替代钥匙......
你知道如何在SQL中使用JOIN吗?您可以将表连接到查找表并搜索值而不是其代理键.
SELECT ... FROM People JOIN Genders USING (gender_id) WHERE gender = 'M'
Run Code Online (Sandbox Code Playgroud)
对于查找表,我喜欢使用自然键.然后,您可以搜索该值'M'而不是该值的代理键.
SELECT ... FROM People WHERE gender = 'M'
Run Code Online (Sandbox Code Playgroud)
您认为创建缓存方案以保留参数数据是否相关?
是.参数数据可能不经常更改,您的性能可以通过减少应用用于获取它们的查询数量而受益.更新值时,将使缓存中的相应条目无效.