踩坑 query method。

问题描述

现有model issue,需要对issues进行排序,根据指定的ID集合来决定记录的位置,比如id包含在(4, 6, 9)中的纪录就排在前面,剩下的排在后面。

使用scope进行处理:

class Issue < ApplicationRecord
.........
IDLIST = [4, 6, 9]
scope :order_by_custom_id, -> {
order_by = ['CASE']
order_by << "WHEN id in (#{IDLIST.join(', ')}) THEN 0"
order_by << 'ELSE 1 END'
order(order_by.join(' '))
}
end

在controller中调用了该scope。刷新页面后,发现服务器报出warning message:

DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "CASE WHEN id in (4,6,9) THEN 0 ELSE 1 END". Non-attribute arguments will be disallowed in Rails 6.0. This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql().

解决方法

其实,报错信息里面已经告诉我解决方法了,但是当时一看懵逼,Dangerous query method?!直接Google了一堆,后面在slack上跟同事求助了下,搞定!

很简单,就是使用warning message里面提到的Arel.sql()方法,将CASE WHEN id in (4,6,9) THEN 0 ELSE 1 END 用Arel.sql() 包起来即可。

修改scope:

class Issue < ApplicationRecord
.........
IDLIST = [4, 6, 9]
scope :order_by_custom_id, -> {
order_by = ['CA 大专栏  Dangerous query method called with non-attribute argument(s)SE']
order_by << "WHEN id in (#{IDLIST.join(', ')}) THEN 0"
order_by << 'ELSE 1 END'
order(Arel.sql(order_by.join(' ')))
}
end

OK!

但是,这个Arel.sql(raw_sql)是什么?

先看看Arel是什么。

官方文档的解释:

Arel is a SQL AST manager for Ruby. It

  • Simplifies the generation of complex SQL queries
  • Adapts to various RDBMSes

文档里面还列出了很多例子,从简单的select * from users 到复杂点的joins table,我猜是因为我接触Rails的时间不长,反正是从来没用过这东西。

Arel.sql(raw_sql) 这个类方法的源代码如下:

def self.sql raw_sql
Arel::Nodes::SqlLiteral.new raw_sql
end

也就是新建了一个Arel::Nodes::SqlLiteral实例,而Arel::Nodes::SqlLiteral为什么是安全的呢?用Arel::Nodes::SqlLiteral 把raw_sql包起来的用意是什么?估计也能猜到,防攻击啥的。果然,Google了下,发现说是可以防止SQL注入的情况。

有些复杂了,脑子暂时消化不了。

此外,文档中有关sanitize_limit 部分也有提到SQL injection的问题。

参考

Arel

A “strict Arel” mode for ActiveRecord to prevent SQL injection vulnerabilities

Dangerous query method called with non-attribute argument(s)的更多相关文章

  1. C#编译问题'System.Collections.Generic.IEnumerable' does not contain a definition for 'Where' and no extension method 'Where' accepting a first argument

    &apos;System.Collections.Generic.IEnumerable<string>&apos; does not contain a definiti ...

  2. 【spring data jpa】repository中使用@Query注解使用hql查询,使用@Param引用参数,报错:For queries with named parameters you need to use provide names for method parameters. Use @Param for query method parameters, or when on

    在spring boot中, repository中使用@Query注解使用hql查询,使用@Param引用参数 如题报错: For queries with named parameters you ...

  3. 编译问题:'<invalid-global-code>' does not contain a definition for 'Store' and no extension method 'XXX' accepting a first argument of type '<invalid-global-code>' could be found

    这是VS2015上的bug. 我碰到的时候,是VS在合并两个分支的代码时,多加了一个}.导致编译语法报错.. 解决办法就是在错误的附近,找找有没有多余的大括号,删掉即可. 这个问题在vs2017上面没 ...

  4. 深入浅出Attribute(三)

    约定: 1.”attribute”和”attributes”均不翻译 2.”property”译为“属性” 3.msdn中的原句不翻译 4.”program entity”译为”语言元素” Attri ...

  5. Using dojo/query(翻译)

    In this tutorial, we will learn about DOM querying and how the dojo/query module allows you to easil ...

  6. Segment Tree Query I & II

    Segment Tree Query I For an integer array (index from 0 to n-1, where n is the size of this array), ...

  7. Lintcode: Segment Tree Query II

    For an array, we can build a SegmentTree for it, each node stores an extra attribute count to denote ...

  8. Lintcode: Segment Tree Query

    For an integer array (index from 0 to n-1, where n is the size of this array), in the corresponding ...

  9. Attribute的理解和认识

    1什么是Attribute? 在网上看到这样一段定义 MADN的定义为:公共语言运行时允许添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法和属性等.A ...

随机推荐

  1. JavaScript学习笔记 - 进阶篇(8)- DOM对象,控制HTML元素

    认识DOM 文档对象模型DOM(Document Object Model)定义访问和处理HTML文档的标准方法.DOM 将HTML文档呈现为带有元素.属性和文本的树结构(节点树). 先来看看下面代码 ...

  2. 吴裕雄--天生自然 PYTHON3开发学习:面向对象

    class MyClass: """一个简单的类实例""" i = 12345 def f(self): return 'hello wor ...

  3. Spire.doc jar包实现word文件添加水印demo

    /** * @create: 2020-02-23 21:50 */ import com.spire.doc.*; import com.spire.doc.documents.WatermarkL ...

  4. 图遍历算法的应用(包括输出长度为l的路径最短最长路径)

    判断从顶点u到v是否有路径 void ExistPath(AdjGraph* G, int u, int v, bool& has) { int w; ArcNode* p; visit[u] ...

  5. day53-线程池

    #1.from concurrent import futures可以开启进程池和线程池.concurrent是包,futures是模块,ThreadPoolExecutor是类,submit是方法. ...

  6. [原]CreateFile中的dwShareMode

    原 总结 API  一直对CreateFile的参数dwDesiredAccess和dwShareMode有什么不同不是很清楚,今天重读 windows核心编程的时候终于豁然开朗了. 真是书读百遍,其 ...

  7. [原]UEFI+GPT启动VHD

    1. 缘起 2. 创建VHD文件并写入系统镜像到VHD文件 2.1 制作VHD文件 2.1.1 纯界面创建 2.1.2 命令行创建 2.2 把系统镜像写入VHD文件 3. 添加VHD文件到系统引导 3 ...

  8. 网络类(IP、dns、网络连接类)

    一.centOS 7 设置DNS方法 使用全新的命令行工具 nmcli 来设置 1.显示当前网络连接 nmcli connection show   NAME UUID TYPE DEVICE eno ...

  9. scala编程(七)——内建控制结构

    几乎所有的 Scala 的控制结构都会产生某个值.这是函数式语言所采用的方式,程序被看成是计算值的活动,因此程序的控件也应当这么做.另外,指令式语言经常具有三元操作符(如 C,C++和 Java 的? ...

  10. Navicat for MySQL远程连接报10038的错误

    #################################################### """ 1.网络检测 1)ping主机可以: 2)telnet ...