关于post:接口测试之post常见数据提交方式

个别咱们在就行接口测试的时候,post申请个别会有多种body参数提交形式。 明天给大家解说一下post申请常见的数据提交形式: 一、multipart/form-datamultipart/form-data 就是http申请中的multipart/form-data,它会将表单的数据处理为一条音讯,以标签为单元,用分隔符离开。既能够上传键值对,也能够上传文件。当上传的字段是文件时,会有Content-Type来阐明文件类型;content-disposition,用来阐明字段的一些信息;因为有boundary隔离,所以multipart/form-data既能够上传文件,也能够上传键值对,它采纳了键值对的形式,所以能够上传多个文件。 二、application/x-www-from-urlencodedapplication/x-www-from-urlencoded,会将表单内的数据转换为键值对,比方,name=xiaoming&pwd = 123 三、application/jsonapplication/json就是以json格局传递数据格式

December 3, 2020 · 1 min · jiezi

关于post:http请求中get和post方法的区别

一、原理区别 个别咱们在浏览器输出一个网址拜访网站都是GET申请;再FORM表单中,能够通过设置Method指定提交形式为GET或者POST提交形式,默认为GET提交形式。 HTTP定义了与服务器交互的不同办法,其中最根本的四种:GET,POST,PUT,DELETE,HEAD,其中GET和HEAD被称为平安办法,因为应用GET和HEAD的HTTP申请不会产生什么动作。不会产生动作意味着GET和HEAD的HTTP申请不会在服务器上产生任何后果。然而平安办法并不是什么动作都不产生,这里的平安办法仅仅指不会批改信息。 依据HTTP标准,POST可能会批改服务器上的资源的申请。比方知乎编写文章,用户提交一篇文章或者一个读者提交评论是通过POST申请来实现的,因为再提交文章或者评论提交后资源(即某个页面)不同了,或者说资源被批改了,这些便是“不平安办法”。 二、应用时最直观的区别最直观的区别就是GET把参数蕴含在URL中,POST通过request body传递参数。 get申请: post申请: 三、为什么get比post更快1.post申请蕴含更多的申请头 因为post须要在申请的body局部蕴含数据,所以会多了几个数据形容局部的首部字段(如:content-type),这其实是微不足道的。 2.最重要的一条,post在真正接收数据之前会先将申请头发送给服务器进行确认,而后才真正发送数据 post申请的过程:(1)浏览器申请tcp连贯(第一次握手)(2)服务器许可进行tcp连贯(第二次握手)(3)浏览器确认,并发送post申请头(第三次握手,这个报文比拟小,所以http会在此时进行第一次数据发送)(4)服务器返回100 Continue响应(5)浏览器发送数据(6)服务器返回200 OK响应get申请的过程:(1)浏览器申请tcp连贯(第一次握手)(2)服务器许可进行tcp连贯(第二次握手)(3)浏览器确认,并发送get申请头和数据(第三次握手,这个报文比拟小,所以http会在此时进行第一次数据发送)(4)服务器返回200 OK响应也就是说,目测get的总耗是post的2/3左右,这个口说无凭,网上曾经有网友进行过测试。 3.get会将数据缓存起来,而post不会 能够做个简短的测试,应用ajax采纳get形式申请静态数据(比方html页面,图片)的时候,如果两次传输的数据雷同,第二次当前耗费的工夫将会在10ms以内(chrome测试),而post每次耗费的工夫都差不多。经测试,chrome和firefox下如果检测到get申请的是动态资源,则会缓存,如果是数据,则不会缓存,然而IE什么都会缓存起来,当然,应该没有人用post去获取静态数据吧,反正我是没见过。 四、面试是个别怎么答复get和post的区别(1)post更平安(不会作为url的一部分,不会被缓存、保留在服务器日志、以及浏览器浏览记录中) (2)post发送的数据更大(get有url长度限度) (3)post能发送更多的数据类型(get只能发送ASCII字符) (4)post比get慢 (5)post用于批改和写入数据,get个别用于搜寻排序和筛选之类的操作(淘宝,支付宝的搜寻查问都是get提交),目标是资源的获取,读取数据 五、测试get和post申请的工具get和post申请个别应用的是接口测试工具,接口测试工具我集体个别应用的是:apipost和jmeter。 apipost是一款国产的接口测试工具和接口文档生成工具,可能满足咱们日常工作当中对于接口测试和接口文档生成的工作需要。接口文档还能够反对多种格局的生成,有在线版、markdown、word版等多种格局的接口文档。 jmeter能够进行接口测试和性能测试,然而对于做单纯的接口测试jmeter操作起来没有apipost应用起来不便。jmeter重点在于压力测试,稳定性测试和负载测试。针对于接口和程序的稳定性设计的一块以软件性能为主接口测试为辅的接口测试工具。 工具下载地址:ApiPost - 可间接生成文档的API调试、管理工具

November 7, 2020 · 1 min · jiezi

vue-axios-post发送复杂对象的一点思考

一、项目情形现在vue项目中,一般使用axios发送请求去后台拉取数据。在某些业务场景中,前端需要在某个字段中发送一个复杂的嵌套对象给后台做保存并处理。虽然axios可配置发送方式(post/get等),但如果不做其他配置,post的数据其实也是拼在请求地址后面,而这种传输方式会有很多问题: 可能数据丢失;get传送的数据长度有limit,如果需要保存大段的中文,会报错;数据不直观,复杂对象的格式会出现问题。二、解决方案 怎么实现使用post方法时,能实现formData方式提交,而且整个请求数据格式能像queryString一样直观。 1、使用QS将数据序列化 //main.jsimport axios from 'axios';Vue.prototype.$axios = axios; // 配置axios的访问方式//demo.vueimport Qs from qs;this.$axios({ method: "post", url: "url", data: reqData, transformRequest: [ function(data){ return Qs.stringify(data) //使用Qs将请求参数序列化 }], headers: { 'Content-Type': 'application/x-www-form-urlencoded' //必须设置传输方式 }}).then((res)=>{ //逻辑代码}2、完成第一步后,可以实现post请求了,请求体为formData的格式,但如果reqData是一个对象嵌套数组的复杂对象,form的格式会变得非常不直观。 //例如obj为一个嵌套多层的复杂对象let reqData = { id: '123', status: '1', data: { innerData: { price: "higher", amount: "2000", }, outerData: { price: "lower", amount: "3000"! }, parts: ['123','234','345','456'] }}参考如上配置,最后请求体中parsed的数据格式会变成如下 对象跟数组的每一项都被拆拼成键值对,数据格式非常不直观,如果此时后台需要将对象整个储存起来,以便下次使用使用录入的数据还原前端页面,则会增加很多额外的转化工作。 3、可以怎样简单处理一下,让它变得像如下图一的get方法一样参数清晰呢? (图一)get方法地参数效果示意图 只需做一个简单的处理,将复杂对象对象变成字符串,再进行传输。 ...

June 4, 2019 · 1 min · jiezi

nodejs-原生的post和get请求

把今天学到的东西记录一下const http = require('http')// querystring 模块提供用于解析和格式化 URL 查询字符串的实用工具const querystring = require('querystring')const server = http.createServer((req, res) => { // 请求的方式 const method = req.method // 获取完整请求url const url = req.url // url路径 const path = url.split('?')[0] // 解析 get请求的参数 为?后面 所以数组下标为1 const getParams = querystring.parse(url.split('?')[1]) // 设置返回的格式 json格式 res.setHeader('Content-type','application/json') // 返回的数据 const resData = { method, url, path, getParams } // 0.如果是Post请求 if (method === 'POST'){ // 接收数据 let postData = '' // chunk为一点点数据,逐渐积累 req.on('data', chunk => { postData += chunk.toString() }) req.on('end', () => { resData.postData = postData // 在这里返回 因为是异步 res.end( // 返回json字字符串 JSON.stringify(resData) ) }) } // 1. 如果是get请求 if (method === 'GET'){ // 返回 res.end( // 返回json字字符串 JSON.stringify(resData) ) }})server.listen(8000)

May 27, 2019 · 1 min · jiezi

npm-scripts-使用指南

一、什么是 npm 脚本?npm 允许在package.json文件里面,使用scripts字段定义脚本命令。 { // ... "scripts": { "build": "node build.js" }}上面代码是package.json文件的一个片段,里面的scripts字段是一个对象。它的每一个属性,对应一段脚本。比如,build命令对应的脚本是node build.js。 命令行下使用npm run命令,就可以执行这段脚本。 $ npm run build# 等同于执行$ node build.js这些定义在package.json里面的脚本,就称为 npm 脚本。它的优点很多。 项目的相关脚本,可以集中在一个地方。不同项目的脚本命令,只要功能相同,就可以有同样的对外接口。用户不需要知道怎么测试你的项目,只要运行npm run test即可。 可以利用 npm 提供的很多辅助功能。查看当前项目的所有 npm 脚本命令,可以使用不带任何参数的npm run命令。$ npm run二、原理npm 脚本的原理非常简单。每当执行npm run,就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令。因此,只要是 Shell(一般是 Bash)可以运行的命令,就可以写在 npm 脚本里面。 比较特别的是,npm run新建的这个 Shell,会将当前目录的node_modules/.bin子目录加入PATH变量,执行结束后,再将PATH变量恢复原样。 这意味着,当前目录的node_modules/.bin子目录里面的所有脚本,都可以直接用脚本名调用,而不必加上路径。比如,当前项目的依赖里面有 Mocha,只要直接写mocha test就可以了。 "test": "mocha test"而不用写成下面这样。 "test": "./node_modules/.bin/mocha test"由于 npm 脚本的唯一要求就是可以在 Shell 执行,因此它不一定是 Node 脚本,任何可执行文件都可以写在里面。 npm 脚本的退出码,也遵守 Shell 脚本规则。如果退出码不是0,npm 就认为这个脚本执行失败。 ...

April 29, 2019 · 2 min · jiezi

学习如何在PostgreSQL中管理安全性

学习如何在PostgreSQL中管理安全性来源 | 愿码(ChainDesk.CN)内容编辑愿码Slogan | 连接每个程序员的故事网站 | http://chaindesk.cn愿码愿景 | 打造全学科IT系统免费课程,助力小白用户、初级工程师0成本免费系统学习、低成本进阶,帮助BAT一线资深工程师成长并利用自身优势创造睡后收入。官方公众号 | 愿码 | 愿码服务号 | 区块链部落免费加入愿码全思维工程师社群 | 任一公众号回复“愿码”两个字获取入群二维码本文阅读时长:17min在处理安全性时,记住这些级别以便以有组织的方式处理与安全相关的问题。· 绑定地址:listen_addresses在文件中 postgresql.conf· 基于主机的访问控制:pg_hba.conf文件· 实例级权限:用户,角色,数据库创建,登录和复制· 数据库级权限:连接,创建模式等· 架构级权限:使用架构并在架构内创建对象· 表级权限:选择,插入,更新等· 列级权限:允许或限制对列的访问· 行级安全性:限制对行的访问为了读取值, PostgreSQL必须确保我们在每个级别都有足够的权限。整个权限链必须是正确的。在本文中,您将学习处理SSL,列级安全性和配置默认权限等的过程。了解绑定地址和连接配置PostgreSQL服务器时,需要做的第一件事就是定义远程访问。默认情况下,PostgreSQL不接受远程连接。重要的是由于PostgreSQL不能监听端口,所以导致它接收不到连接。如果我们尝试连接,错误消息实际上将来自操作系统。假设有一个使用默认配置的数据库服务器192.168.0.123,将发生以下情况:iMac:~ hs$ telnet 192.168.0.123 5432 Trying 192.168.0.123… telnet: connect to address 192.168.0.123: Connection refused telnet: Unable to connect to remote hostTelnet尝试在端口上创建连接,5432并立即被远程框拒绝。从外面看,看起来PostgreSQL根本就没有运行。成功连接的关键可以在postgresql.conf文件中找到:# - Connection Settings - # shop_addresses =‘localhost’ # 要监听的IP地址; # 逗号分隔的地址列表; # defaults为’localhost’; 使用’*‘表示所有# (更改需要重启)该listen_addresses设置将告诉PostgreSQL要监听的地址。从技术上讲,这些地址是绑定地址。这究竟意味着什么?假设我们的机器中有四个IP地址。我们这些IP地址只监听其中的三个。PostgreSQL只考虑这三个IP的请求,而不考虑第四个。如果我们放入 *,PostgreSQL会监听分配给您机器的每个IP。但是,有更多与连接管理相关的设置对于理解非常重要。它们如下:#port = 5432 # (change requires restart) max_connections = 100 # (change requires restart) # Note: Increasing max_connections costs ~400 bytes of # shared memory per # connection slot, plus lock space # (see max_locks_per_transaction). #superuser_reserved_connections = 3 # (change requires restart) #unix_socket_directories = ‘/tmp’ # comma-separated list of directories # (change requires restart) #unix_socket_group = ’’ # (change requires restart) #unix_socket_permissions = 0777 # begin with 0 to use octal notation # (change requires restart)首先,PostgreSQL侦听单个TCP端口,默认值为5432。请记住,PostgreSQL只会侦听单个端口。每当有请求进入时,postmaster将创建一个新进程来处理连接。默认情况下,最多允许100个普通连接。最重要的是,为超级用户保留了三个额外的连接。这意味着我们可以拥有97个连接加上三个超级用户或100个超级用户连接。处理SSLPostgreSQL允许我们加密服务器和客户端之间的传输。加密非常有用,特别是如果我们进行远距离通信。SSL提供了一种简单而安全的方式来确保没有人能够收听您的通信。在本节中,我们将学习如何设置SSL。首先要做的是在服务器启动时将ssl参数设置on为postgresql.conf文件。在下一步中,我们可以将SSL证书放入$PGDATA目录中。如果我们不希望证书位于其他目录中,请更改以下参数:#ssl_cert_file = ‘server.crt’ # (change requires restart) #ssl_key_file = ‘server.key’ # (change requires restart) #ssl_ca_file = ’’ # (change requires restart) #ssl_crl_file = ’’ # (change requires restart)如果我们要使用自签名证书,请执行以下步骤:openssl req -new -text -out server.req回答OpenSSL提出的问题。确保我们输入本地主机名作为通用名称。我们可以将密码留空。此调用将生成一个受密码保护的密钥; 它不会接受长度少于四个字符的密码短语。要删除密码(如果要自动启动服务器,则必须如此),请运行以下命令:openssl rsa -in privkey.pem -out server.keyrm privkey.pem输入旧密码以解锁现有密钥。现在,执行此操作将证书转换为自签名证书,并将密钥和证书复制到服务器将查找的位置:openssl req -x509 -in server.req -text -key server.key -out server.crt执行此操作后,请确保文件具有正确的权限集:chmod og-rwx server.key一旦将适当的规则放入pg_hba.conf文件中,我们就可以使用SSL连接到您的服务器。要验证我们确实使用SSL,请考虑签出该pg_stat_ssl功能。它将告诉我们每个连接以及它是否使用SSL,它将提供有关加密的一些重要信息:test=# \d pg_stat_sslView “pg_catalog.pg_stat_ssl"Column | Type | Modifiers ————-+———-+———– pid | integer | ssl | boolean | version | text | cipher | text | bits | integer | compression | boolean |clientdn | text |如果ssl进程的字段包含true; PostgreSQL做了我们期望它做的事情:postgres=# select * from pg_stat_ssl; -[ RECORD 1 ] —————————- pid | 20075ssl | t version | TLSv1.2cipher | ECDHE-RSA-AES256-GCM-SHA384 bits | 256compression | f clientdn |处理实例级安全性到目前为止,我们已经配置了绑定地址,我们告诉PostgreSQL使用哪种IP范围进行身份验证。到目前为止,配置纯粹与网络相关。在下一步中,我们可以将注意力转移到实例级别的权限。最重要的是要知道PostgreSQL中的用户存在于实例级别。如果我们创建一个用户,它不仅在一个数据库中可见; 它可以被所有数据库看到。用户可能只具有访问单个数据库的权限,但基本上用户是在实例级别创建的。对于那些刚接触PostgreSQL的人来说,还有一件事要记住:用户和角色是一回事。CREATE ROLE和CREATE USER子句有不同的默认值(字面上,唯一的区别是LOGIN默认情况下角色没有得到属性),但在一天结束时,用户和角色是相同的。因此,CREATE ROLE和CREATE USER子句支持完全相同的语法:test=# \h CREATE USERCommand: CREATE USERDescription: define a new database roleSyntax:CREATE USER name [ [ WITH ] option [ … ] ]where option can be:SUPERUSER | NOSUPERUSER| CREATEDB | NOCREATEDB| CREATEROLE | NOCREATEROLE| INHERIT | NOINHERIT| LOGIN | NOLOGIN| REPLICATION | NOREPLICATION| BYPASSRLS | NOBYPASSRLS| CONNECTION LIMIT connlimit| [ ENCRYPTED ] PASSWORD ‘password’| VALID UNTIL ’timestamp’| IN ROLE role_name [, …]| IN GROUP role_name [, …]| ROLE role_name [, …]| ADMIN role_name [, …]| USER role_name [, …]| SYSID uid让我们逐个讨论这些语法元素。我们首先看到的是用户可以是超级用户或普通用户。如果某人被标记为a SUPERUSER ,则不再有普通用户必须面对的任何限制。A SUPERUSER 可以根据需要删除对象(数据库等)。下一个重要的事情是它在实例级别上获取创建新数据库的权限。规则是这样的:创建者总是自动成为对象的所有者(除非另有说明,否则可以使用该CREATE DATABASE子句)。美丽的是,对象所有者也可以再次丢弃一个对象。下一个重要的是INHERIT/ NOINHERITclause。如果INHERIT设置了子句(这是默认值),则用户可以继承其他用户的权限。使用继承权限允许我们使用角色,这是抽象权限的好方法。例如,我们可以创建角色bookkeeper并使许多其他角色继承bookkeeper。我们的想法是bookkeeper,即使我们有很多人从事会计工作,我们也只需要告诉PostgreSQL一次允许做什么。该LOGIN/ NOLOGIN子句定义一个角色是否可以登录到该实例。在理论介绍之后,是时候实际创建用户并看看在实际示例中如何使用事物:test=# CREATE ROLE bookkeeper NOLOGIN; CREATE ROLE test=# CREATE ROLE joe LOGIN; CREATE ROLE test=# GRANT bookkeeper TO joe; GRANT ROLE这里做的第一件事bookkeeper是创建一个名为的角色。请注意,我们不希望人们以身份登录bookkeeper,因此角色标记为NOLOGIN。另请注意,NOLOGIN如果使用该CREATE ROLE子句,则为默认值。如果您更喜欢该CREATE USER子句,则默认设置为LOGIN。然后,joe创建角色并标记为LOGIN。最后,将bookkeeper角色分配给joe角色,以便他可以执行bookkeeper实际允许的所有操作。一旦用户到位,我们可以测试到目前为止我们拥有的内容:[hs@zenbook ~]$ psql test -U bookkeeper psql: FATAL: role “bookkeeper” is not permitted to log in正如所料,该bookkeeper角色不允许登录系统。如果joe角色尝试登录会发生什么? [hs@zenbook ~]$ psql test -U joe … test=>这实际上将按预期工作。但请注意,命令提示符已更改。这只是PostgreSQL向您显示您未以超级用户身份登录的一种方式。创建用户后,可能需要对其进行修改。我们可能想要改变的一件事是密码。在PostgreSQL中,允许用户更改自己的密码。下面是它的工作原理:test=> ALTER ROLE joe PASSWORD ‘abc’; ALTER ROLE test=> SELECT current_user; current_user ————– joe (1 row)该ALTER ROLE条款(或ALTER USER)将允许我们改变它可以创建用户时设置大多数设置。但是,管理用户还有很多。在许多情况下,我们希望为用户分配特殊参数。该ALTER USER条款为我们提供了这样做的方法:ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter { TO | = } { value | DEFAULT } ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter FROM CURRENT ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] RESET configuration_parameter ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] RESET ALL语法非常简单,非常简单。为了描述为什么这非常有用,我添加了一个真实的例子。让我们假设Joe碰巧住在毛里求斯岛上。当他登录时,即使他的数据库服务器位于欧洲,他也希望自己在他自己的时区:test=> ALTER ROLE joe SET TimeZone = ‘UTC-4’; ALTER ROLE test=> SELECT now(); now ——————————- 2017-01-09 20:36:48.571584+01 (1 row) test=> q [hs@zenbook ~]$ psql test -U joe … test=> SELECT now(); now ——————————- 2017-01-09 23:36:53.357845+04 (1 row)该ALTER ROLE子句将修改用户。一旦joe重新连接,就会为他设置时区。时区不会立即更改。您应该重新连接或使用SET … TO DEFAULT子句。这里重要的是这对于某些内存参数也是可能的,例如work_mem等等。数据库级别的安全性在实例级别配置用户之后,可以深入挖掘并查看在数据库级别可以执行的操作。出现的第一个主要问题是:我们明确允许Joe登录数据库实例,但是谁或什么允许Joe实际连接到其中一个数据库?也许我们不希望Joe访问系统中的所有数据库。限制对某些数据库的访问正是我们在此级别上可以实现的目标。对于数据库,可以使用GRANT子句设置以下权限:GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [, …] | ALL [ PRIVILEGES ] } ON DATABASE database_name [, …] TO role_specification [, …] [ WITH GRANT OPTION ] 数据库级别有两个主要权限值得密切关注:· CREATE:这允许某人在数据库中创建模式。请注意,CREATE子句不允许创建表; 它是关于模式的。在PostgreSQL中,表位于模式中,因此您必须首先进入模式级别才能创建表。· CONNECT:这允许有人连接到数据库。现在的问题是:没有人明确CONNECT为joe角色分配权限,那么这些权限实际上来自何处?答案是:有一个叫做的东西public,类似于Unix世界。如果世界被允许做某事,那么joe,谁是一般公众的一部分。最重要的是,public它不是一个角色,它可以被删除和重命名。我们可以简单地将其视为系统中每个人的等价物。因此,为了确保不是每个人都可以随时连接到任何数据库,CONNECT可能必须从公众中撤销。为此,我们可以以超级用户身份进行连接并解决问题:[hs@zenbook ~]$ psql test -U postgres … test=# REVOKE ALL ON DATABASE test FROM public; REVOKE test=# \q [hs@zenbook ~]$ psql test -U joe psql: FATAL: permission denied for database “test” DETAIL: User does not have CONNECT privilege.我们可以看到,该joe角色不再允许连接。此时,只有超级用户才能进行测试。通常,postgres 即使在创建其他数据库之前,最好还是从数据库中撤消权限。这个概念背后的想法是,这些权限将不再存在于所有新创建的数据库中。如果某人需要访问某个数据库,则必须明确授予权限。权利不再自动存在。如果我们想允许joe角色连接到测试数据库,请以超级用户身份尝试以下行:[hs@zenbook ~]$ psql test -U postgres … test=# GRANT CONNECT ON DATABASE test TO bookkeeper; GRANT test=# \q [hs@zenbook ~]$ psql test -U joe … test=>基本上,这里有两种选择:· 我们可以joe直接允许角色,以便只有joe角色才能连接。· 或者,我们可以为该bookkeeper角色授予权限。请记住,joe角色将继承角色的所有权限bookkeeper,因此,如果我们希望所有会计师都能够连接到数据库,则为角色分配权限bookkeeper似乎是一个有吸引力的想法。如果我们为该bookkeeper角色授予权限,则它没有风险,因为该角色不允许首先登录到该实例,因此它纯粹作为权限来源。处理列级安全性在某些情况下,并不是每个人都可以看到所有数据。想象一下银行,有些人可能会看到有关银行帐户的全部信息,而其他人可能仅限于数据的一部分。在现实世界的情况下,可能不允许某人阅读余额栏,或者有人可能看不到人民贷款的利率。另一个例子是,人们可以看到人们的个人资料,但不能看到他们的照片或其他私人信息。现在的问题是:如何使用列级安全性?为了证明这一点,我们将向属于该joe角色的现有表添加一列:test=> ALTER TABLE t_useful ADD COLUMN name text; ALTER TABLE该表现在由两列组成。该示例的目标是确保用户只能看到其中一列:test=> \d t_useful Table “public.t_useful” Column | Type | Modifiers ——–+———+———– id | integer | name | text |作为超级用户,让我们创建一个用户并让它访问包含我们表的模式:test=# CREATE ROLE paul LOGIN; CREATE ROLE test=# GRANT CONNECT ON DATABASE test TO paul; GRANT test=# GRANT USAGE ON SCHEMA public TO paul; GRANTCONNECT被撤销了public。因此,明确授予绝对是必要的,以确保我们甚至可以到达桌面。该SELECT权限可以赋予paul角色:test=# GRANT SELECT (id) ON t_useful TO paul; GRANT 基本上,这已经足够了。已经可以以用户身份连接到数据库paul并阅读该列:[hs@zenbook ~]$ psql test -U paul … test=> SELECT id FROM t_useful; id —- (0 rows)如果我们使用列级权限,请记住一件重要的事情,我们应该停止使用SELECT *,因为它不再起作用了:test=> SELECT * FROM t_useful; ERROR: permission denied for relation t_useful仍然意味着所有列,但由于无法访问所有列,事情将立即出错。配置默认权限到目前为止,已经配置了很多东西。如果将新表添加到系统会发生什么?逐个处理这些表并设置适当的权限可能会非常痛苦和风险。如果这些事情会自动发生,那不是很好吗?这正是该ALTER DEFAULT PRIVILEGES条款的作用。这个想法是为用户提供一个选项,让PostgreSQL在对象出现后立即自动设置所需的权限。有人不能再忘记设置这些权利了。以下清单显示了语法规范的第一部分:postgres=# \h ALTER DEFAULT PRIVILEGESCommand: ALTER DEFAULT PRIVILEGESDescription: define default access privilegesSyntax:ALTER DEFAULT PRIVILEGES [ FOR { ROLE | USER } target_role [, …] ] [ IN SCHEMA schema_name [, …] ] abbreviated_grant_or_revokewhere abbreviated_grant_or_revoke is one of:GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }[, …] | ALL [ PRIVILEGES ] }ON TABLESTO { [ GROUP ] role_name | PUBLIC } [, …] [ WITH GRANT OPTION ]…基本上,语法与GRANT子句类似,因此使用起来简单直观。为了向我们展示它的工作原理,我编写了一个简单的例子。我们的想法是,如果joe角色创建了一个表,该paul角色将自动使用它:test=# ALTER DEFAULT PRIVILEGES FOR ROLE joe IN SCHEMA public GRANT ALL ON TABLES TO paul; ALTER DEFAULT PRIVILEGES让我们joe现在作为角色连接并创建一个表:[hs@zenbook ~]$ psql test -U joe … test=> CREATE TABLE t_user (id serial, name text, passwd text); CREATE TABLE作为paul角色连接将证明该表已分配给适当的权限集:[hs@zenbook ~]$ psql test -U paul … test=> SELECT * FROM t_user; id | name | passwd —-+——+——– (0 row ...

April 11, 2019 · 4 min · jiezi

都9102年了,还问GET和POST的区别

1 前言最近看了一些同学的面经,发现无论什么技术岗位,还是会问到 get 和 post 的区别,而搜索出来的答案并不能让我们装得一手好逼,那就让我们从 HTTP 报文的角度来撸一波,从而搞明白他们的区别。2 标准答案在开撸之前吗,让我们先看一下标准答案长什么样子 w3school: GET 对比 POST。标准答案很美好,但是在面试的时候把下面的表格甩面试官一脸,估计会装逼不成反被*。分类GETPOST后退按钮/刷新无害数据会被重新提交(浏览器应该告知用户数据会被重新提交)。书签可收藏为书签不可收藏为书签缓存能被缓存不能缓存编码类型application/x-www-form-urlencodedapplication/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。历史参数保留在浏览器历史中。参数不会保存在浏览器历史中。对数据长度的限制是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。无限制。对数据类型的限制只允许 ASCII 字符。没有限制。也允许二进制数据。安全性与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。在发送密码或其他敏感信息时绝不要使用 GET !POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。可见性数据在 URL 中对所有人都是可见的。数据不会显示在 URL 中。注意,并不是说标准答案有误,上述区别在大部分浏览器上是存在的,因为这些浏览器实现了 HTTP 标准。但是,前面列举的只是浏览器实现上的区别,而不是 get 和 post 的本质区别。3 GET 和 POST 报文上的区别先下结论,GET 和 POST 方法没有实质区别,只是报文格式不同。GET 和 POST 只是 HTTP 协议中两种请求方式,而 HTTP 协议是基于 TCP/IP 的应用层协议,无论 GET 还是 POST,用的都是同一个传输层协议,所以在传输上,没有区别。报文格式上,不带参数时,最大区别就是第一行方法名不同POST方法请求报文第一行是这样的 POST /uri HTTP/1.1 \r\nGET方法请求报文第一行是这样的 GET /uri HTTP/1.1 \r\n是的,不带参数时他们的区别就仅仅是报文的前几个字符不同而已带参数时报文的区别呢? 在约定中,GET 方法的参数应该放在 url 中,POST 方法参数应该放在 body 中举个例子,如果参数是 name=chengqm, age=22。GET 方法简约版报文是这样的GET /index.php?name=qiming.c&age=22 HTTP/1.1Host: localhostPOST 方法简约版报文是这样的POST /index.php HTTP/1.1Host: localhostContent-Type: application/x-www-form-urlencodedname=qiming.c&age=22现在我们知道了两种方法本质上是 TCP 连接,没有差别,也就是说,如果我不按规范来也是可以的。我们可以在 URL 上写参数,然后方法使用 POST;也可以在 Body 写参数,然后方法使用 GET。当然,这需要服务端支持。4. 常见问题GET 方法参数写法是固定的吗?在约定中,我们的参数是写在 ? 后面,用 & 分割。我们知道,解析报文的过程是通过获取 TCP 数据,用正则等工具从数据中获取 Header 和 Body,从而提取参数。也就是说,我们可以自己约定参数的写法,只要服务端能够解释出来就行,一种比较流行的写法是 http://www.example.com/user/name/chengqm/age/22。POST 方法比 GET 方法安全?按照网上大部分文章的解释,POST 比 GET 安全,因为数据在地址栏上不可见。然而,从传输的角度来说,他们都是不安全的,因为 HTTP 在网络上是明文传输的,只要在网络节点上捉包,就能完整地获取数据报文。要想安全传输,就只有加密,也就是 HTTPS。GET 方法的长度限制是怎么回事?在网上看到很多关于两者区别的文章都有这一条,提到浏览器地址栏输入的参数是有限的。首先说明一点,HTTP 协议没有 Body 和 URL 的长度限制,对 URL 限制的大多是浏览器和服务器的原因。浏览器原因就不说了,服务器是因为处理长 URL 要消耗比较多的资源,为了性能和安全(防止恶意构造长 URL 来攻击)考虑,会给 URL 长度加限制。POST 方法会产生两个TCP数据包?有些文章中提到,post 会将 header 和 body 分开发送,先发送 header,服务端返回 100 状态码再发送 body。HTTP 协议中没有明确说明 POST 会产生两个 TCP 数据包,而且实际测试(Chrome)发现,header 和 body 不会分开发送。所以,header 和 body 分开发送是部分浏览器或框架的请求方法,不属于 post 必然行为。5 talk is cheap show me the code如果对 get 和 post 报文区别有疑惑,直接起一个 Socket 服务端,然后封装简单的 HTTP 处理方法,直接观察和处理 HTTP 报文,就能一目了然#!/usr/bin/env python# -- coding: utf-8 --import socketHOST, PORT = ‘’, 23333def server_run(): listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) listen_socket.bind((HOST, PORT)) listen_socket.listen(1) print ‘Serving HTTP on port %s …’ % PORT while True: # 接受连接 client_connection, client_address = listen_socket.accept() handle_request(client_connection)def handle_request(client_connection): # 获取请求报文 request = ’’ while True: recv_data = client_connection.recv(2400) recv_data = recv_data.decode() request += recv_data if len(recv_data) < 2400: break # 解析首行 first_line_array = request.split(’\r\n’)[0].split(’ ‘) # 分离 header 和 body space_line_index = request.index(’\r\n\r\n’) header = request[0: space_line_index] body = request[space_line_index + 4:] # 打印请求报文 print(request) # 返回报文 http_response = “”"\HTTP/1.1 200 OK<!DOCTYPE html><html><head> <title>Hello, World!</title></head><body><p style=“color: green”>Hello, World!</p></body></html>""" client_connection.sendall(http_response) client_connection.close()if name == ‘main’: server_run()上面代码就是简单的打印请求报文然后返回 HelloWorld 的 html 页面,我们运行起来[root@chengqm shell]# python httpserver.py Serving HTTP on port 23333 …然后从浏览器中请求看看打印出来的报文然后就可以手动证明上述说法,比如说要测试 header 和 body 是否分开传输,由于代码没有返回 100 状态码,如果我们 post 请求成功就说明是一起传输的(Chrome/postman)。又比如 w3school 里面说 URL 的最大长度是 2048 个字符,那我们在代码里面加上一句计算 uri 长度的代码…# 解析首行first_line_array = request.split(’\r\n’)[0].split(’ ‘)print(‘uri长度: %s’ % len(first_line_array[1]))…我们用 postman 直接发送超过 2048 个字符的请求看看然后我们可以得出结论,url 长度限制是某些浏览器和服务器的限制,和 HTTP 协议没有关系。到此,我们可以愉快地装逼了 :)参考:99%的人都理解错了HTTP中GET与POST的区别关于HTTP GET 和 POSTw3school: HTTP 方法:GET 对比 POSTwikipedia: 超文本传输协议RFC 2068 ...

February 12, 2019 · 2 min · jiezi

在yii2中,让你action参数支持POST数据的小方法

我们先来看一段代码class RaController extends Controller { public $enableCsrfValidation = false; public function actionSay($username = ‘’,$city = ‘’){ echo “{$username} 来自 {$city}”; }}这里actionSay对应的url为index.php?r=ra/say,而 $username 和 $city 值的获取来自于url的参数,比如index.php?r=ra/say&username=abei2017&city=洛阳总结 在yii2中,action参数都是来自于GET。但是有的时候你可能需要让action的参数来自于POST请求,怎么办?重载runAction即可,yii2为控制器提供了runAction方法,它负责生成一个具体的Action对象并传递参数,我们可以通过复写它来实现,你可以看下yii2的生命周期来对其进行更好的了解。那就开始干吧~,对上面的代码复写runActionclass RaController extends Controller { public $enableCsrfValidation = false; public function runAction($id, $params = []){ $params = ArrayHelper::merge(Yii::$app->request->post(),$params); return parent::runAction($id, $params); } public function actionSay($username = ‘’,$city = ‘’){ echo “{$username} 来自 {$city}”; }}复写了runAction后,它将作用于此控制器的所有action,当然你也可以通过runAction的$id来作用于某个action。比如public function runAction($id, $params = []){ if($id == ‘say’){ $params = ArrayHelper::merge(Yii::$app->request->post(),$params); } return parent::runAction($id, $params);}现在去试试吧,对say动作提交POST数据username和city,成功接收。 ...

September 26, 2018 · 1 min · jiezi