比如,你输入一个手机号,进行查询,要把你手机号的值,查询是 like 还是=,数据是 string 还是 int,模糊还是精准查询,全部前端拼给后端。。。
这种方案可行吗。。。
1
onepunch 2020-04-17 14:43:42 +08:00
模糊查询前端做
|
2
racecoder00 2020-04-17 14:43:49 +08:00 1
不怕前端传个 drop table?
|
3
dremy 2020-04-17 14:44:18 +08:00 via iPhone
SQL 注入了解一下,公司分分钟倒闭
|
4
opengps 2020-04-17 14:44:38 +08:00
关键词,和是否 like,可以传
至于 string 还是 int 啥意思? |
5
Jooooooooo 2020-04-17 14:46:59 +08:00
可行
关注一下防注入就行 不过虽然是可行, 方案不合理啊, 前端关心的是"模糊查询"而不是"模糊查询用 like" |
6
BreezeInWind 2020-04-17 14:49:29 +08:00
传一串字符串,如果本身其实是可以精确匹配到的,但是查询人以为是模糊匹配的,因而传的是 like,后端怎么处理呢?一串非常长的数字,本来应该是字符串形式存放的,查询人以为是数字,传的是 int,此时又该怎么处理呢
|
7
jatesun 2020-04-17 14:50:35 +08:00
算了,这种事前端就别揽了
|
8
zycojamie OP [' tempMatchType ": " 5,4 ", " propertyName ": " name,mobile, " propertyvaluel ": ",13541218876 "),
{" tempMatchType ": " 7 ", " propertyName ": " age " " propertyvaluel ": " 12 ", " tempType ": " Integer "}, tempMatchType ": " 11 ", " propertyName ": " role.id ", " prepertyvalue1 ": " 1,2,3,4 ", " tempType ": " List < Long >"}] 翻译成 hql = where ( name like %张三%' or mobile = 13541218876 and age > 12 and role.idin ( 1.2.3.4 ) 前端就要把查询参数封装成上面那种数组 |
9
zycojamie OP @jatesun 后端架构师说,为了他们拜托大量 if else,所以要求前端按照他们订的查询规则封装请求参数。。。
|
10
littleylv 2020-04-17 14:54:03 +08:00
我觉得楼主的意思并不是说前端要拼接好 ‘mobile like '%123%'’这样提交给后端,而是使用
{'field': 'mobile', 'value': '123', 'is_fuzzy': true} 这样传给后端,让后端去拼接。 |
11
loading 2020-04-17 14:57:18 +08:00 via Android
先在手机号前后拼接%,然后参数查询,用 like 。
如果有注入风险,请大佬们马上提醒我。 |
12
loading 2020-04-17 14:58:17 +08:00 via Android
sql 参数拼接还是不难的,没几行。
谁都是 crud boy 。 |
13
zycojamie OP @littleylv 类似,但要求更复杂些(把大于等于,小于,小于等于,等于)都约定好是什么特定值,然后前端传参的时候,就要传(大于等于,小于,小于等于,等于)
|
14
littleylv 2020-04-17 15:00:00 +08:00
|
15
Rwing 2020-04-17 15:00:40 +08:00
GraphQL 欢迎你
|
16
yukiloh 2020-04-17 15:03:28 +08:00 via Android 2
这种接口别被我逮到,不然就直接送你出名
|
17
ZSeptember 2020-04-17 15:04:33 +08:00
这不是很正常的吗,难道不同的查询就要新增加一个接口?
RESTful 一般只提供一个查询接口,参考 https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md#971-filter-operations |
19
wangxiaoaer 2020-04-17 15:08:40 +08:00
@yukiloh #16 这种接口有什么问题吗?
假如一些业务系统就是很需要很精确的查询:比较、类别、模糊 /精确切换等你怎么做??? 现在后端要求是前端把这些非常精细的条件传过去,后端翻译成 sql,又没让前端直接拼、传 sql,只要后端在生成 sql 的时候做好防注入,有什么问题? |
20
pap3r 2020-04-17 15:09:53 +08:00
前端爸爸不帮后端儿子擦屁股
|
21
jziwenchen 2020-04-17 15:12:21 +08:00
graphql 可以了解看看
|
22
sun1991 2020-04-17 15:14:58 +08:00
要区分具体需求是什么再谈实现, 不要一上来就一顿喷...
曾经做过的灵活可定制查询界面大概就是这样的实现. |
23
lneoi 2020-04-17 15:15:16 +08:00
这样处理太繁琐了吧 有点像是做后台的大量查询的需求
|
24
fumichael 2020-04-17 15:15:44 +08:00
像这个一样?前端可以组装查询条件呀
但不能后端直接接收前端参数作为 sql 语句 我想到的是,可以使用枚举进行处理 https://i.loli.net/2020/04/17/AfIQ4U7weZtDdSB.png |
25
purensong 2020-04-17 15:16:08 +08:00
graphQL 不错
|
26
cedoo22 2020-04-17 15:18:52 +08:00
没安全规则吗???让前端拼。。😂😂
|
27
z1154505909 2020-04-17 15:21:19 +08:00
前端拼接????头一次听说
|
28
CismonX 2020-04-17 15:24:59 +08:00 1
突然想起来之前我们学校有个英语课在线答题系统,前端传给后端的参数是一条条完整的 SQL 。
有好事者试着传了个 DROP TABLE xxx,然后就没有然后了😂 |
29
zycojamie OP 安全的话,后端说他们通过框架层去校验和拦截,前端需要把传统的查询参数由{ user:"张三"}变成{ user:{
matchType:"1", propertyName:"user", propertyValue:"张三", dataType:"string" }} matchType 为 1 代表“包含” |
30
Erroad 2020-04-17 15:51:44 +08:00
前端把 ui“翻译”成参数还是很正常的,拼 sql 是肯定不行的,让前端拼 sql 给后端的后端都是 xx
|
31
littleylv 2020-04-17 15:54:12 +08:00
|
32
wyz123723 2020-04-17 15:57:23 +08:00
现在后端真是越来越烂 /懒了
|
33
wellsc 2020-04-17 16:00:49 +08:00
graphql + 1
|
34
1et 2020-04-17 16:03:14 +08:00
string 和 int 确实有点迷,传 like 、=没什么问题,比如 name:3 默认等值查询,name_like:3 是模糊查询
|
35
javapythongo 2020-04-17 16:10:51 +08:00
我觉得可以
|
36
buffzty 2020-04-17 16:13:50 +08:00
我就是这样做的.已经用了一年多了.如果项目很小,开发速度第一可以试试.缺点就是只能普通查询,如果查询有 join 的需要手动写规则
下面这个是我查询列表的一个通用方法.新加一个模型只需要设置一下 model 类型 和 filter 映射和 order 映射 用这套接口速度起飞,但有局限性 ```php // Base controller public function lists(): Json { $json = new JsonRes(); [$page, $limit, $filter, $order, $extra] = $this->getListParam(); $scene = $extra['scene'] ?? $this->model::SCENE['default']; $where = $this->model::buildWhereMap($filter); $fmtOrder = $this->model::buildFmtOrder($order); if ( $scene === $this->model::SCENE['admin'] && !$this->isAdminUser() ) { return $this->noAuth(); } [$list, $count] = $this->model::getListNotThrowEmptyEx($page, $limit, $this->model::NEED_COUNT, $where, [], $order); $fmtList = []; /** @var \app\model\Base $model */ foreach ($list as $model) { $fmtList[] = $model->getFmtDetail($scene); } $json->setData([ 'list' => $fmtList, ]); $json->setPage($page); $json->setLimit($limit); $json->setCount($count); return json($json); } // Base Model /** * 根据 filter 构建查询条件. * * @param array|null $filterList * @param array $filterFieldMapDbField * @return array */ public static function buildWhereMap($filterList, array $filterFieldMapDbField = []): array { $filterFieldMapDbField = empty($filterFieldMapDbField) ? static::FILTER_FIELD_MAP_DB_FIELD : $filterFieldMapDbField; $map = []; if ( !is_array($filterList) ) { return []; } foreach ($filterList as $filterField => $item) { if ( $item instanceof Closure ) { $map[] = $item; continue; } if ( !is_array($item) || !array_key_exists('condition', $item) || !array_key_exists('val', $item) ) { continue; } if ( $item['val'] === '' || $item['condition'] === Condition::TYPE['undefined'] || !in_array($item['condition'], Condition::TYPE, true) ) { continue; } if ( !array_key_exists($filterField, $filterFieldMapDbField) ) { continue; } $dbField = $filterFieldMapDbField[$filterField]; $condition = Condition::DB_CONDITION[$item['condition']]; $map[] = [ $dbField, $condition, Condition::formatVal($item['condition'], $item['val']), ]; } return $map; } ``` 前端代码: ```typescript // 一个模型只需要定义下面这些 就可以使用通用增删改查 5 个接口了 type Model = Expert const route = '/expert' type FilterKeys = | 'id' | 'ctime' | 'expertCode' | 'name' | 'userName' | 'departmentId' | 'orgCode' | 'orgName' | 'provCode' | 'cityCode' | 'countyCode' | 'provName' | 'cityName' | 'countyName' | 'level' | 'intro' | 'type' | 'mobile' | 'phone' | 'email' | 'qq' | 'wx' | 'remark' | 'serviceType' type OrderKeys = 'id' | 'ctime' type Scene = 'admin' | 'default' interface QueryExtra extends BaseExtra<Scene> {} type ActGetListParam = GetListParam<FilterKeys, OrderKeys, QueryExtra> type AddData = Omit<Model, 'adeptLabelList' | 'department' | 'id'> type EditData = AddData & Pick<Model, 'id'> export async function lists<T = Model>(data: ActGetListParam) { return bpost<{ list: T[] }>({ url: route + '/list', data, }) } ``` |
37
buffzty 2020-04-17 16:14:56 +08:00
谁能告诉我这破站到底怎么发代码?
|
38
baiyi 2020-04-17 16:19:57 +08:00
GraphQL +10086
|
39
6IbA2bj5ip3tK49j 2020-04-17 16:40:17 +08:00 via iPhone
这不就是那个男人经常推广的场景吗?
|
41
vitoliu 2020-04-17 17:59:53 +08:00
防 sql 注入的工具很多,后端随便引一下就解决了,而且的确能摆脱大量的判空和 if else 。
参数混淆啥的也都没做,而且看参数名应该是 B 端系统吧,用户量少这么干的确也没啥问题。 不过前端传驼峰不传下划线的确让我感觉挺不得劲的哈哈哈。 |
42
areless 2020-04-17 18:06:44 +08:00 via Android
可行,写了一套这样的前后端,本来想用。感觉那就每天没事干,盯着前端写 SQL 就可以了
|
43
IGJacklove 2020-04-17 18:09:47 +08:00
@ZSeptember 感觉一个接口和这个也没啥关系吧,换个方式,加个枚举什么的都比前端传 like 强吧
|
44
Deffi 2020-04-17 18:18:31 +08:00 1
我是移动端,要是考虑版本迭代,逻辑变更,我不会用这种接口。前端应该尽量少做逻辑处理
|
45
red2dog 2020-04-17 18:19:44 +08:00
graphql ++
|
46
guyeu 2020-04-17 18:51:11 +08:00
在有很多复杂查询的场景使用自己的 DSL 代替若干个接口是有意义的,但需要注意的是不应该让前端拼 SQL,而且需要对 DSL 的应用范围进行限制,最好是从设计上避免危险操作的可能性。
|
47
guyeu 2020-04-17 18:52:53 +08:00
不拼 SQL 的主要原因是让数据库和客户端解耦,因为在不通的架构模式下 SQL 的写法可能有较大差异,这不应该影响客户端实现,而表结构也不应该对客户端透明。
|
48
k9990009 2020-04-17 18:59:05 +08:00 via Android
可以的,但是不要前端拼 SQL 。以前我们前端人手不够,前端也是后端写的。自定义参数解析。然后后端调用根据关键字,这个关键字正好是 mybatis plus 的方法名,通过反射调用自动拼。后端只要继承默认实现 CRUD 就好了。比如前端传 name_leftlike,只要写前端就好了,超爽。后端做参数过滤就好了。
|
50
randyo 2020-04-17 19:05:34 +08:00 via Android
流量不要钱吗,前端为了摆脱复杂数据果断抛回去让后端自己写
|
51
rioshikelong121 2020-04-17 19:08:09 +08:00
这样前端也得懂表结构了 而且复杂的 sql 怎么处理。还得单独写接口吧。
|
52
kohos 2020-04-17 19:18:51 +08:00 via Android
这种如果是 where 后面全部靠前端提供的参数生成的话,很不安全,例如楼主的接口,改一下 roleId 就能操作其他角色的数据了,后端想偷懒也不是这样做的
|
53
component 2020-04-17 19:47:46 +08:00
GraphQL 了解一下
|
54
jugelizi 2020-04-17 19:50:53 +08:00 via iPhone
可行
但不是拼接。 应该是传 json k v 指定查询类型 以及查询内容 |
55
MilletChili 2020-04-17 19:51:20 +08:00
一般的查询,我都是叫前端去拼的,虽然我就是那个前端
start_num = int(request.GET.get('start_num') or 0) # 起始数 get_num = int(request.GET.get('get_num') or 10) # 需求数 filters = request.GET.get('filters') # 筛选条件 sorts = request.GET.get('sorts') # 排序条件 want_fileds = request.GET.get('want_fileds') # 指定需要的字段 is_distinct = request.GET.get('is_distinct') # 是否去重 qset = model.objects.using(using_database).all() if filters: # print('筛选条件:',filters) qset = filterHelper(filters, qset) if sorts: # print('排序条件:',sorts) qset = qset.order_by(*sorts.split(',')) if is_distinct == 'yes': qset = qset.distinct() all_num = qset.count() # 总个数 qset = qset[start_num: start_num + get_num] if want_fileds: data_list = createSerializers(model, want_fileds.split(','))(qset, many=True).data else: data_list = Ser_L(qset, many=True).data data = {'all_num': all_num, 'data_list': data_list} |
57
wushigejiajia01 2020-04-17 20:19:01 +08:00 via Android
楼主大致意思: 前端传参,要把参数类型,以及查询范围都传给后端,这样后端能把接口做的很灵活多用
应该是这个意思吧? 只要不是由前端拼接 SQL,这没啥问题啊 |
58
shadeofgod 2020-04-17 21:30:25 +08:00
这届后端还是不行 🐶
|
59
jswh 2020-04-17 21:44:49 +08:00
管理后台可以,产品中最好不要。这事我也干过,本质上可所谓的 restful 或者 graphql 的想法是一样的,就是定义一套自己的 DSL 免得老是做相同的事情。
|
60
lizhuoli 2020-04-17 21:53:46 +08:00 via iPhone
重新自己实现一个垃圾版本 GraphQL ?意义何在
|
61
hooopo 2020-04-17 21:56:44 +08:00 via Android
graphql 了解一下
|
62
puilu 2020-04-18 00:19:07 +08:00
这届后端不行
|
63
hq136234303 2020-04-18 00:19:35 +08:00
@zycojamie 你们架构师真的可爱。如果是前端加密做的话 终有一天解开 sql 注入 会爽的飞起的。。。。
|
64
a1562619919 2020-04-18 02:42:38 +08:00 via Android
数据量极小的模糊查询前端做,比如手机登录帐号。但数据多到超过几十个了明显前端不该处理,或者涉及业务的数据尽量不让前端处理,前端可以模糊查询一下个人非业务的缓存数据(个人姓名手机号这种)
|
65
icy37785 2020-04-18 03:15:25 +08:00
GraphQL + 10086
|
66
bllue 2020-04-18 05:43:48 +08:00
架构师应该拎得清
只要避免前端拼接后端拿来直接用的情况 |
68
yufeng0681 2020-04-18 08:11:26 +08:00
我能想到 前端能拒绝的理由:
如果有三个终端 需要使用这个功能。 三个终端的开发都要懂 SQL,都要完整测试,不合理,也浪费成本。 |
69
SyncWorld 2020-04-18 08:41:53 +08:00
直接传 SQL 岂不是美包包~
|
70
qce7 2020-04-18 08:59:21 +08:00
我们这边用 Yii2 的 DSL
// 过滤条件 // 过滤条件按需使用,没有过滤条件就不传 filter "filter": { // and 表示 "且",也支持 or,但是实际业务用的比较少而且性能不佳 or 不建议使用 "and": [ // like 条件 {"mobile": {"like": "1"}}, // level = 1 {"level": 1}, // 范围条件 id in [2, 5, 9] {"id": {"in": [2, 5, 9]}}, // createdAt > 0 {"createdAt": {"gt":0}}, // createdAt < 10000000000 {"createdAt": {"lt":10000000000}} ] } // 每页记录数,后端默认 10 条 "perPage": 10, // 请求页数 "page": 1, // 排序值,优先级从前到后“-”表示倒序 "sort": "-isDefault,-isCertified,-id" } |
71
SjwNo1 2020-04-18 09:48:36 +08:00
graphql 吧,sql 不安全不太好
|
72
michaelcheng 2020-04-18 09:53:11 +08:00
复杂的查询传参还是可以的,不一定是要 sql ,语义化的传参,约定参数类型、运算符、值约束等
|
73
a852695 2020-04-18 09:59:56 +08:00
如果是直接传 sql 不可,但是玩着玩着就变成了直接传 sql,不信试试看?后端尝到了甜头。
如果是拼约定字符串可以,玩着玩着,自己都不知道约定了啥。 |
74
onfuns 2020-04-18 10:16:11 +08:00
可行,不过这种方案都是用在内网的系统,可以减少很多的工作量。外网的应用还是应该规规矩矩的,现在的安全可是很敏感了。
|
75
royzxq 2020-04-18 12:58:07 +08:00
这不就是传说中 apiJSON 的场景吗, 让你们后端用啊(
|