在请求URL中公开表名和字段名

Jos*_*eph 6 mysql security field client-side

我的任务是创建这个Joomla组件(是的,joomla;但它不相关),一位教授告诉我,我应该尽可能使我的代码变得动态(代码需要较少的维护)并避免硬编码.我们最初想到的方法是获取url参数,将它们转换为对象,并将它们传递给查询.

假设我们想在"酒店"表中读取ID为#1的酒店.假设该表有"hotel_id","hotel_name"和其他一些字段.

现在,我们制作sql查询字符串的方法是解析看起来像这样的url请求:

index.php?task=view&table=hotels&hotel_id=1&param1=something&param2=somethingelse
Run Code Online (Sandbox Code Playgroud)

并将其转换为这样的PHP对象(以JSON等效显示,更易于理解):

obj = {
  'table':'hotel',
  'conditions':{
        'hotel_id':'1',
        'param1':'something',
        'param2':'somethingelse'
}
Run Code Online (Sandbox Code Playgroud)

并且SQL查询将是这样的,其中条件循环并附加到字符串中,其中WHERE子句的字段和值是对象的键和值(为了方便,仍然以JSON形式):

SELECT * FROM obj.table WHERE hotel_id=1 AND param1=something and so on...
Run Code Online (Sandbox Code Playgroud)

困扰我的问题是在请求网址中公开了表名和字段名.我知道这会产生安全风险,暴露出只应该向服务器端看到的项目.我正在考虑的当前解决方案是为客户端的每个表和字段提供别名 - 但这将是硬编码,这违反了他的政策.此外,如果我这样做,并且有一千个别名表,那就不实用了.

没有这样做的正确方法是什么:

  1. 硬编码的东西
  2. 保持代码动态和适应性

编辑:

关于任意查询(我忘了包含这个),当前在后端停止它们的是一个函数,它从硬编码对象(更像是这里显示的配置文件)中引用,并通过拾取来解析url输出参数或匹配它们.

配置看起来像:

// 'hotels' here is the table name. instead of parsing the url for a table name
// php will just find the table from this config. if no match, return error.
// reduces risk of arbitrary tables.

'hotels' => array(      

  // fields and their types, used to identify what filter to use

  'structure' => array(  
    'hotel_id'=>'int',
    'name'=>'string',
    'description'=>'string',
    'featured'=>'boolean',
    'published'=>'boolean'
  ),

   //these are the list of 'tasks' and accepted parameters, based on the ones above
   //these are the actual parameter names which i said were the same as field names
   //the ones in 'values' are usually values for inserting and updating
   //the ones in 'conditions' are the ones used in the WHERE part of the query

  'operations' =>array(  
    'add' => array(
      'values' => array('name','description','featured'),
      'conditions' => array()
    ),
    'view' => array(
    'values' => array(),
    'conditions' => array('hotel_id')
    ),
    'edit' => array(
    'values' => array('name','description','featured'),
    'conditions' => array('hotel_id')
    ),
    'remove' => array(
    'values' => array(),
    'conditions' => array('hotel_id')
    )
  )
)
Run Code Online (Sandbox Code Playgroud)

所以,从该配置列表:

  • 如果为任务发送的参数未完成,则服务器返回错误.
  • 如果来自url的参数加倍,则仅读取第一个参数.
  • 不在配置中的任何其他参数将被丢弃
  • 如果不允许该任务,则不会列出该表
  • 如果任务不存在,服务器将返回错误
  • 如果没有表,则服务器返回错误

在看到joomla中使用此策略的组件后,我实际上对此进行了模式化.它将模型和控制器简化为4个动态函数,这些函数将是CRUD,只留下配置文件是以后唯一可编辑的文件(这就是我对动态代码的意思,如果需要更多的表,我只添加表和任务)但我担心它可能会带来一些我可能还不知道的安全隐患.

有替代方案的想法吗?

tc.*_*tc. 1

我对在 URL 和数据库中使用相同(或非常相似)的名称没有任何问题 - 当然,您可能会“暴露”实现细节,但如果您在 URL 和数据库中选择完全不同的名称,那么您'我们可能会选择不好的名字。我也喜欢一致的命名——如果每个人对所有东西的称呼都略有不同,那么与编码人员/测试人员/客户的沟通就会变得更加困难。

让我烦恼的是你让用户在你的数据库上运行任意查询。http://.../index.php?table=users&user_id=1, 说?或者http://.../index.php?table=users&password=password(并不是说您应该以明文形式存储密码)?或者http://.../index.php?table=users&age=11

如果连接到数据库的用户与坐在 Web 浏览器前的用户具有相同的权限,那么这可能是有意义的。一般来说,情况并非如此,因此您需要一些层来了解用户是什么以及不允许查看什么,并且通过白名单该层更容易正确编写。

(如果您已将足够的逻辑放入存储过程中,那么它可能会起作用,但是您的存储过程将硬编码列名称......)