前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python技术面试题(十二)--SQL注入、项目部署

python技术面试题(十二)--SQL注入、项目部署

作者头像
小闫同学啊
发布2019-07-18 14:58:36
8360
发布2019-07-18 14:58:36
举报
文章被收录于专栏:小闫笔记小闫笔记

正文共: 6626 字 7 图 预计阅读时间: 17 分钟

每日分享

It's up to you how far you go. If you don't try, you'll never know!

能走多远取决于你自己,如果不愿尝试,你将永远不会知道!

小闫语录

长路漫漫,唯夜作伴。如果因前路的未知,丧失了尝试的勇气,前路将永远变成未知。

插播一条消息

3月11日邓先生询问一个问题,今天才看到,回复的时候发现已经过了48小时,无法主动联系你。所以在此回答您的问题,向您表示歉意。因为后台是机器人回复,好多人在逗它,导致消息超多,所以您的消息被淹没了,不好意思哈。

问题

请问,在执行docket的时候提示内存空间不足,怎么办?(我想了一会,查了一下百度,不清楚docket是什么?,你应该是想问docker吧....如果不是请告知)

思路

因为不了解您的具体情况,无法做出准确的判断,所以向您提供一些解决的思路:

1.查看Docker的磁盘使用情况:

代码语言:javascript
复制
docker system df

2.清理磁盘,删除关闭的容器、一些没用的数据卷和网络,还有那些没有tag的镜像:

代码语言:javascript
复制
docker system prune

3.更加彻底的清理:

代码语言:javascript
复制
docker system prune -a

2、3命令慎用,它会将你暂时关闭的容器以及暂时没有使用的docker镜像都删除。同时docker system命令是1.13版本之后才有的命令,建议使用新版的docker。

4.另外一种思路是查看/var/lib/docker/目录下的文件,docker的镜像和容器等等所有文件都在这个目录下,看看真正占用空间的是什么文件。

5.如果是上线的项目,日志文件会超大,可以将日志文件备份后删除,当然这方法有点傻,日志还是会生成。那么可以限制容器的日志大小。如果是自己线下测试的项目,日志可能并不是很大,视情况而定。

6.最后是一招百试百灵的方法:重启docker。俗话说没有什么是『重启』解决不了的问题,如果有,那就多重启几次。

如果还是无法解决,可以看本文docker相关的命令尝试动手解决,也可以选择CSDN、Google上查询相关经验贴。

笔试题

1.什么是SQL注入,如何防止,ORM中如何防止?

答:SQL注入就是利用正常的SQL语句,获取到了非法的数据。防御措施大体有以下几点:对用户的输入进行校验,可以通过正则表达式或限制长度;对单引号和 --等特殊字符进行转义;不要动态的拼接SQL语句,使用参数化的SQL(下面的例子就是使用参数化解决SQL注入)查询数据库;永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的连接数据库;不要把机密的信息直接存放,而是经过hash加盐加密等措施保护敏感数据;应用的异常信息应该尽可能的少提示,最好使用自定义的错误信息对原始错误信息进行包装。(永远不要信任用户的任何输入,很有可能对面是一个想要攻击你的黑客!!!!)ORM底层其实是使用了参数化的形式执行SQL语句,而且ORM接口是属于内部封装机制,对外无接口,理论上很安全了,但是凡事没有绝对,万一要攻击你数据库的是一位高手呢?那么怎么办呢?如果是这样,说明你公司已经十分的厉害了,能让一个人耗费老鼻子劲攻击,到这种程度,你公司的财富应该也请得起比对面黑客更牛x的人了吧,还是不用你操心,开不开心。当然这是一句玩笑话,毕竟小编知识有限,如果你找到了ORM攻击的方式与解决措施,别忘了联系我。

举例说明SQL注入

我们在书写查询语句的时候,有可能涉及到占位符进行数据替换,后面接入用户输入的用户名和密码之类的数据:

代码语言:javascript
复制
select * from user where username = '%s' and password = '%s';

如果用户输入了一些特殊的字符,那么会产生一些严重的后果(拖库,直接获取到所有的数据)。比如用户的用户名输入了 root' or 1 --,然后将其拼接到上述的SQL语句中,会出现下面的现象:

代码语言:javascript
复制
select * from user where username = 'root' or 1 -- ' and password = '%s';

-- 代表注释的意思

上述查询条件where为 username='root'或者是 1,后面的密码因为 --的出现变成了注释,不会执行,因此只对用户名进行校验。username无论对与错,因为是逻辑运算符 ,后面 1代表真,判断条件永远成立,那么直接返回查询结果。

就问你可怕不可怕,当然上面只是利用简单的一个例子进行说明。你肯定会问,那么就不能防止SQL注入吗?答案是可以的。那就是参数化,问题又来了,什么是参数化呢?就是我们在python数据库编程的时候,将 SQL 语句的所有数据参数存在一个元组(或者列表、字典)中传递给 execute 函数的第二个参数。下面演示效果:

代码语言:javascript
复制
from  pymysql import *
# 创建数据库连接
db_connect = Connect(host='localhost',port=3306,database='test_db',user='root',password='123123',charset='utf8')
# 获取游标
cur = db_connect.cursor()
# 请输入一个查询的ID
query_id = input('please input ID:')
# 使用参数化来解决SQL注入
# 以字符串形式书写SQL语句,因为SQL语句中也会出现字符串,避免单引号或者双引号的错误,我们直接使用三引号进行书写
sql_str = ''' select * from students where id = %s '''
# 在准备SQL字符串时,不能再直接拼接参数
# 而是将参数做成一个元组,列表,字典,传入到 execute 方法中
# 下面执行SQL语句,并传入元组形式的参数
cur.execute(sql_str, (query_id,))
# 获取所有的数据
result = cur.fetchall()
# 遍历出所有的结果
for t in result:
    print(t)
# 关闭游标
cur.close()
# 关闭数据库
db_connect.close()

部署相关知识

部署方面最重要的知识分为两块,一块是Nginx,一块是Docker,下面就这两块内容,进行阐述。

1. Nginx

Nginx是一款基于异步框架的轻量级服务器,它支持高并发量,能高效的处理相关业务。平时我们用来做web服务器、缓存服务器以及反向代理服务器,当然它还能做邮件服务器。那么它除了支持高并发,还有什么优点吗?内存消耗少,配置简单还稳定,扔到远程服务器上基本就不用管了。如果公司想用有限的资源解决更多的问题,那么它是首选,因为它便宜啊,还支持多系统。最最重要的一点,就是它善于处理静态文件,因此我们常常将静态文件放到Nginx上,减少后端服务器的压力。

1.1相关命令

查看Nginx状态(active或者dead):

代码语言:javascript
复制
systemctl status nginx

启动|停止|重启|重新加载Nginx服务器:

代码语言:javascript
复制
systemctl start|stop|restart|reload nginx

其实上面的命令用来开启关闭还是太麻烦,那么可以使用下面的命令替换:

代码语言:javascript
复制
nginx                   启动
nginx -s stop|reload    停止|重载

检查配置文件是否符合语法要求(超级重要,在工作中只要配置文件发生改变,马上要执行的命令就是这个,检查完之后再重新启动。否则最后出错,难以排查问题):

代码语言:javascript
复制
nginx -t

查看当前系统下开启服务所占用端口的信息:

代码语言:javascript
复制
netstat -tnulp

配置文件目录:

代码语言:javascript
复制
/etc/nginx/conf.d

文件的结构要明白:

代码语言:javascript
复制
全局配置段
http配置段
    server配置段 # 项目或者应用的网站
        location配置段 # 网站里面的文件url

1.2 Nginx访问原理

浏览器拆分URL地址获取相关的请求。分为地址、端口和路径关键字。其中每个请求的目的是根据地址找服务器,根据端口找服务器上的应用,路径关键字用于location匹配。

url:

代码语言:javascript
复制
协议:// 网站地址:端口 (/)路径地址 ? 参数

server配置段:

代码语言:javascript
复制
server {
    listen 端口;
    server_name 主机名;
    ...
}

location配置:

代码语言:javascript
复制
location optional_modifier location_match {...}

optional_modifier:匹配条件;location_match是匹配的样式;{...}:要执行的操作。

另外补充一点:location常见的动作中,alias 相当于$uri 直接去alias指定的目录下请求就可以了,是绝对路径。而root 则是到root指定的目录下的$uri/ 去找,是相对路径。

1.3正向代理&反向代理

从安全性来讲,正向代理可以保护客户端的身份,而反向代理则是保护服务器的身份。

我们翻阅天朝的墙时,使用的V**就是正向代理。当我们爬取数据,采用高匿IP时,也是正向代理,毕竟要保护爬虫工程师的人生安全嘛。那么什么是反向代理呢?我们采用的Nginx就是反向代理啊?忘记了吗?

1.4Nginx代理模块

关键参数就是 proxy_pass,设定的是请求跳转后的地址,也就是被代理服务器的地址和被映射的URI。

代码语言:javascript
复制
server{
    listen 99;
    location / {
        proxy_pass http://192.168.33.24:888/ethanyan/;
    }
}

一定要注意 proxy_pass中的地址结尾处的 /。有没有结果大不相同。

1.5负载均衡(超级重要)

上面我们使用 proxy_pass的方式实现了Nginx反向代理,请求后端。当网站的访问量越来越多的时候,一台服务器就有点力不从心了,那么怎么办,就是采用负载均衡。简单的理解就是多准备几台服务器,就是这么简单粗暴。

负载均衡就用到了我们Nginx中的 upstream模块。它定义了一个后端服务地址的集合列表,每个后端服务使用一个server命令指定。它还可以通过一系列的属性设置负载均衡中的主机情况。

代码语言:javascript
复制
down            当前主机故障时,直接进行隔离
backup          后备主机,当线上主机故障或者访问量剧增服务器繁忙时,才开启
max_fails       允许请求的最大失败数,默认是1,配合下一个参数使用
fail_timeout    经历max_fails次失败后,暂停服务的时间,默认为10s。

最后说一个是常识,但是超级重要的命令:

代码语言:javascript
复制
curl [option] [url]
如:
curl http://www.ethanyan.com # 执行之后请求的页面内容就显示在屏幕上了,作为一个运维人员,或者一个后端服务器工程师,这个命令如果不晓得就说不过去了

1.6Nginx调度算法

内置策略

轮询:默认算法,按服务器顺序依次转发相关请求。(要雨露均沾嘛)

加权轮询:指定轮询权重,值越大,分配到的几率就越大,适合后端服务器性能不均衡的情况。

ip_hash:按访问IP的哈希结果分配请求,让同一个IP访问固定一台服务器,有效的解决动态网页会话共享问题。

第三方算法

fair:这个是按服务器的响应时间来分配请求的,当某一台服务器请求无延迟,直接就将请求交给他了。

url_hash:按url的哈希结果来分配请求,使得同一个URL定向到同一台后端服务器,可提高后端缓存服务器的效率。

1.7日志

日志地址: /var/log/nginx

还可以定制日志,在下面的文件中进行配置:

代码语言:javascript
复制
/etc/nginx/nginx.conf

2. Docker

一提到Docker,你脑中蹦出来的词是什么呢?虚拟化、容器等等。如果是这些,那么说明你了解到了它的精髓。它没有固定的概念,曾有人这么描述:Docker是一种快速解决生产问题的技术手段。文绉绉,难以理解。

Docker其实就是将开发环境完整封装的一个容器,它解决了开发工程师和运维人员之间的甩锅操作,开发是什么样子,测试就是什么样子。还有部署项目的时候,怎么实现负载均衡,手动一台台配啊?那不得累死,直接将Docker搬过去啊,下载打开运行成功,立马搞定。

2.1相关操作

启动docker:

代码语言:javascript
复制
systemctl start docker

查看Docker的状态:

代码语言:javascript
复制
systemctl status docker

Docker服务命令:

代码语言:javascript
复制
docker start | stop | restart docker

删除命令:

代码语言:javascript
复制
你还真看啊,涉及到删除命令,哥劝你用的时候手动查一下,利用查询的时间思考一下

搜索镜像:

代码语言:javascript
复制
docker search [image_name]

先在本地仓库找,找不到去网络仓库找

获取镜像:

代码语言:javascript
复制
docker pull [image_name]

查看镜像:

代码语言:javascript
复制
docker images
# 查看一个镜像
docker images [image_name]

查看镜像历史信息:

代码语言:javascript
复制
docker history nginx

查看历史操作过的命令以及产生文件的大小

重命名,打标签:

代码语言:javascript
复制
docker tag [old_image]:[old_version] [new_image]:[new_version]

删除镜像:

代码语言:javascript
复制
docker rmi [IMAGE ID]
或:
docker rmi [image]:[image_version]

Docker的家目录:

代码语言:javascript
复制
/var/lib/docker

将Docker的镜像导出,进行备份

代码语言:javascript
复制
docker save -o [包文件] [镜像]
如:
docker save -o nginx.tar ethanyan-nginx

导入镜像

代码语言:javascript
复制
docker load < [image.tar_name]
docker load --input [image.tar_name]

查看正在运行的容器:

代码语言:javascript
复制
docker ps

查看所有运行过的容器:

代码语言:javascript
复制
docker ps -a

启动容器;

代码语言:javascript
复制
docker run <参数,可选> [docker_image] [执行的命令]
# 让Docker容器在后台以守护形式运行
docker run -d [docker_image]
# 启动已经终止的容器
docker start [container_id]

创建并进入到容器里面:

代码语言:javascript
复制
docker run --name [container_name] -it [docker_image] /bin/bash
--name    给容器定义一个名字
-i        让容器的标准输入保持打开
-t        让docker分配一个伪终端,并绑定在容器的标准输入上

进入到容器里面:

代码语言:javascript
复制
docker exec -it <容器id> /bin/bash

关闭容器:

代码语言:javascript
复制
docker stop [container_id]

基于容器创建镜像:

代码语言:javascript
复制
docker commit -m <注释> -a <作者> [container_id] [new_image]:[new_version]

查看容器所有的详细信息:

代码语言:javascript
复制
docker inspect [container_name]

查看容器运行日志:

代码语言:javascript
复制
docker logs [container_id]

2.2私有仓库部署

1.下载registry镜像:

代码语言:javascript
复制
docker pull registry

2.启动容器:

代码语言:javascript
复制
docker run -d -p 5000:5000 --restart=always registry

--restart 代表的是什么时间重启

3.检查容器效果:

代码语言:javascript
复制
curl 127.0.0.1:5000/v2/_catelog

4.配置容器权限:

代码语言:javascript
复制
vim /etc/docker/daemon.json
{"registry-mirrors":["http://74f21445.m.daocloud.io"], "insecureregistries":["192.168.8.14: 5000"]}

私有仓库ip地址是宿主机的ip,而且ip两侧要有双引号

5.重启docker服务:

代码语言:javascript
复制
systemctl restart docker
systemctl status docker

效果查看

代码语言:javascript
复制
docker start <container_id>
docker tag ubuntu-mini 192.168.33.24:5000/buntu-16.04-mini
docker push 192.168.33.24:5000/ubuntu-16.04-mini
docker pull 192.168.33.24:5000/ubuntu-16.04-mini

打标签时版本号如果不指定,默认是latest。

优质文章推荐:

公众号使用指南

redis操作命令总结

前端中那些让你头疼的英文单词

Flask框架重点知识总结回顾

项目重点知识点详解

难点理解&面试题问答

flask框架中的一些常见问题

团队开发注意事项

浅谈密码加密

Django框架中的英文单词

Django中数据库的相关操作

DRF框架中的英文单词

重点内容回顾-DRF

Django相关知识点回顾

美多商城项目导航帖

项目重要技术点介绍

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈技术精选 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 每日分享
  • 插播一条消息
    • 问题
      • 思路
      • 笔试题
        • 1.什么是SQL注入,如何防止,ORM中如何防止?
          • 举例说明SQL注入
          • 部署相关知识
            • 1. Nginx
              • 1.1相关命令
              • 1.2 Nginx访问原理
              • 1.3正向代理&反向代理
              • 1.4Nginx代理模块
              • 1.5负载均衡(超级重要)
              • 1.6Nginx调度算法
              • 1.7日志
            • 2. Docker
              • 2.1相关操作
              • 2.2私有仓库部署
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档