当前位置:网站首页>How MySQL's allowMultiQueries flag relates to JDBC and jOOQ
How MySQL's allowMultiQueries flag relates to JDBC and jOOQ
2022-07-31 11:17:00 【DebugUsery】
MySQL的JDBC连接器There is a security feature,叫做 [allowMultiQueries](https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-security.html)``false
当关闭时,It prevent throughJDBC使用MySQLA useful but potentially dangerous in function.
try (Statement s = connection.createStatement()) {
try {
s.execute("create table t (i int);");
// This doesn't work, by default:
s.executeUpdate(""" insert into t values (1); insert into t values (2); """);
}
finally {
s.execute("drop table t");
}
}
复制代码
在默认情况下,The above content will produce a grammar mistakes.
Exception in thread "main" java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insert into t values (2)' at line 2
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.StatementImpl.executeUpdateInternal(StatementImpl.java:1333)
at com.mysql.cj.jdbc.StatementImpl.executeLargeUpdate(StatementImpl.java:2106)
at com.mysql.cj.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1243)
at org.jooq.testscripts.JDBC.main(JDBC.java:34)
复制代码
除非我们在JDBC连接URL中打开allowMultiQueries=true
,Otherwise we can't chain statements like this.
jdbc:mysql://localhost/test?allowMultiQueries=true
而现在,突然间,Statement batch normal finished,Two records are inserted into the table.
Why has this function?
The security features help prevent一些SQL注入漏洞.Harder to additional statements now,One thousand do you have a series of bad idea,比如说,你的字符串.
// Terrible idea:
s.executeUpdate("insert into t values (" + value + ")");
复制代码
因为,如果value
包含字符串"1); drop table t;"
呢?这在语法上是正确的,所以它将 "按预期 "执行. It is not very good.
Now don't have a false sense of security.Turn off this feature does not prevent allSQL注入漏洞.Just let this particular hole harder.There are still different ways,This lack of use of bind variables will cause the attacker to read your data,例如,通过Based on the time of attack.
SQLThe injection of risk needs to be taken seriously.The best solution is to always write with bind variables staticSQL(例如:
PreparedStatement
、存储过程或jOOQ),或者用jOOQ这样的SQLThe generator to write dynamicSQL.
在jOOQ中使用allowMultiQueries
在使用jOOQ时,The above situation is difficult to happen.jOOQThe default usage is to use.
- The code generator toGenerate database metadata
- DSL生成SQL
只有在极少数情况下,You can use普通的SQL模板来解决jOOQThe specific function shortage problem,在这种情况下,Template language will help you avoid series string and metSQL注入漏洞.
If you are the kind of person who carefully,你可以In your building中添加一个注释处理器,防止在jOOQ中使用普通的SQL API(Any use will not be the default compiler,Unless you explicitly selection).
所以,MySQLLogo for youjOOQUse is not really useful.事实上,It is even a problem,因为jOOQInternal relies on the generated as described above statement batch.Here are some when you closeallowMultiQueries=false
When not working function(Most of them can also be applied toMariaDB,btw).
GROUP_CONCAT
每当你在MySQL的jOOQ中使用GROUP_CONCAT
,jOOQWill assume that you haven't changeMySQL的默认值为 [@@group_concat_max_length](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_group_concat_max_len)
.The default value is very low,即1024
.And this value is not only to prevent large data sets string polymerization,And just silently fail,This leads to the value of the error!
当使用GROUP_CONCAT
在MySQL中模拟JSON_ARRAYAGG()
,在产生的JSONArrays are commonly have a detectable grammar mistakes,But when you just want to have some string value,For example, when a comma-separated list of,情况就不是这样了.(See the previous blog,Why don't we also use the localJSON_ARRAYAGG()
支持).
所以,Every time you useGROUP_CONCAT
(或者jOOQIn the internal use it some simulation)时,jOOQWill do is preset and attach the following statement.
-- These are prepended
SET @t = @@group_concat_max_len;
SET @@group_concat_max_len = 4294967295;
-- Actual statement here:
SELECT group_concat(A SEPARATOR ',') FROM T;
-- These are appended
SET @@group_concat_max_len = @t;
复制代码
If you have fixed the system or session variable,你可以通过改变Settings.renderGroupConcatMaxLenSessionVariable
Sign to close the function.
Create or replace function
许多SQLDialects of the stored procedure、函数、The trigger and the other does not contain data storage object has aCREATE OR REPLACE
语法.This is a very useful syntactic sugar,Used to write this,而不是.
-- Much simpler
CREATE OR REPLACE FUNCTION f ...
-- Than this
DROP FUNCTION IF EXISTS f;
CREATE FUNCTION f ...
复制代码
但同样的,如果你关闭了allowMultiQueries=false
,那么jOOQIn this simulation can't work,You will get a grammar mistakes.在这里,jOOQCan do nothing to help you.You must manually run the two statements,Instead of using the convenient syntax.
FOR UPDATE WAIT n
Many dialects are aFOR UPDATE WAIT n
语法,Allow for the pessimistic locks to specify aWAIT
超时,例如:
SELECT *
FROM t
FOR UPDATE WAIT n;
复制代码
MySQL 8.0.26还不支持这个功能,但自从jOOQ 3.15和#11543以来,We are using this syntax to simulate the grammar.
SET @t = @@innodb_lock_wait_timeout;
SET @@innodb_lock_wait_timeout = 2;
SELECT *
FROM t
FOR UPDATE;
SET @@innodb_lock_wait_timeout = @t;
复制代码
另一件事是,If you have the following situation will not be able to workallowMultiQueries=false
匿名块
Many procedural language supports procedural code of anonymous block,Is not stored in the procedural code in the process of.这是很有意义的.毕竟,We also do not have to keep all theSQLStored in the view,So why should we willPL/SQL、T-SQL、PL/pgSQLStored in the storage process such as?Especially when you want to dynamically generate the block,这可能非常有用,使用jOOQOn the server rather than on the client side run some logic,减少往返次数.
在Oracle中,你可以写.
BEGIN
INSERT INTO t VALUES (1);
IF TRUE THEN
INSERT INTO t VALUES (2);
END IF;
END;
复制代码
jOOQ从3.12To support this anonymous block.看看关于IF
Statement of the manual page.你可以写
// Assuming the usual static imports:
import static org.jooq.impl.DSL.*;
import static org.jooq.impl.SQLDataType;
// Then write:
Variable<Integer> i = var("i", INTEGER);
ctx.begin(
declare(i).set(1),
if_(i.eq(0)).then(
insertInto(A).columns(A.COL).values(1)
).elsif(i.eq(1)).then(
insertInto(B).columns(B.COL).values(2)
).else_(
insertInto(C).columns(C.COL).values(3)
)
).execute();
复制代码
This in those in favor of the anonymous block dialect translation into and execute the correct process of anonymous block,但不幸的是,MySQL 8.0.26还不支持,那么我们该怎么做?我们生成一个 "匿名 "过程,调用它,And then again to give up.
CREATE PROCEDURE block_1629705082441_2328258()
BEGIN
DECLARE i INT;
SET i = 1;
IF i = 0 THEN
INSERT INTO a (col) VALUES (1);
ELSEIF i = 1 THEN
INSERT INTO b (col) VALUES (2);
ELSE
INSERT INTO c (col) VALUES (3);
END IF;
END;
CALL block_1629705082441_2328258();
DROP PROCEDURE block_1629705082441_2328258;
复制代码
我的意思是,为什么不呢?但是,这又依赖于allowMultiQueries=true
,否则,JDBCThe driver will refuse this statement.
关于jOOQThe procedural languageAPI的更多信息,请参考: https://blog.jooq.org/vendor-agnostic-dynamic-procedural-logic-with-jooq/
结论
MySQL的JDBCDrivers have a very good security features,Designed to prevent someSQL注入的情况,Especially when the users useJDBCConnection manualSQL执行时.The team there is always a poor people don't knowSQL注入,So wrong,打开了潘多拉的盒子.For these purposes,allowMultiQueries=false
是一个合理的默认值.
当按照jOOQThe intent to usejOOQ时,SQLThe possibility of injection to小得多 .This does not include pureSQL模板的使用,But this article does not apply.另一方面,jOOQ内部依靠allowMultiQueries=true
,In order to realize some need to perform multiple statements in a roundtrip simulation.
未来的jOOQVersion will allow configuration more query execution model,To make the above situation can be used as many times perform.更多细节见#9645.
在此之前,如果你想从jOOQ和MySQLGet the most benefits,请确保在你的jOOQConnected to the openallowMultiQueries=true
,May remain closed elsewhere.
边栏推荐
- 使用内存映射加快PyTorch数据集的读取
- 502 bad gateway原因、解决方法
- deeplab implements its own remote sensing geological segmentation dataset
- Docker搭建Mysql主从复制
- The principle of v-model
- unity computeshader的可读写buffer
- [ 图 论 ]二分图判定及其匹配(基础+提高)
- mysql 自动添加创建时间、更新时间
- If the value of the enum map does not exist, deserialization is not performed
- 7 天能找到 Go 工作吗?学学 Go 数组和指针试试
猜你喜欢
【软件工程之美 - 专栏笔记】33 | 测试工具:为什么不应该通过QQ/微信/邮件报Bug?
数据持久化技术——MP
The most complete phpmyadmin vulnerability summary
才22岁!这位'00后'博士拟任职985高校!
[Part 1 of Cloud Native Monitoring Series] A detailed explanation of Prometheus monitoring system
最全phpmyadmin漏洞汇总
deeplab实现自己遥感地质分割数据集
下课看着文档走回实验室,我重新拾起了遗忘的SQL运算符
A Method for Ensuring Data Consistency of Multi-Party Subsystems
5 个开源的 Rust Web 开发框架,你选择哪个?
随机推荐
瑞吉外卖项目:文件的上传与下载
新人学习小熊派华为iot介绍
MySQL 行级锁(行锁、临键锁、间隙锁)
数据持久化技术——MP
下课看着文档走回实验室,我重新拾起了遗忘的SQL运算符
应用层基础 —— 认识URL
Curl 命令使用
[ 图 论 ]二分图判定及其匹配(基础+提高)
Yarn安装配置(vsftpd安装配置)
3D激光SLAM:LeGO-LOAM论文解读---点云分割部分
便利贴--46{基于移动端长页中分页加载逻辑封装}
St. Regis Takeaway Project: File Upload and Download
实现弹框组件
ApiPost is really fragrant and powerful, it's time to throw away Postman and Swagger
3D激光SLAM:LeGO-LOAM论文解读---完整篇
Many mock tools, this time I chose the right one
SQLServer2019 installation (Windows)
The most complete phpmyadmin vulnerability summary
Use jOOQ to write vendor-agnostic SQL with JPA's native query or @Formula.
deeplab implements its own remote sensing geological segmentation dataset