HTTPS请求HTTP接口被浏览器阻塞,python实现websocket客户端,websocket服务器,跨域问题,dwebsocket,https,拦截,服务端

发表时间:2020-03-05

1 背景

由于公司前端的页面部署在以https(加了证书)协议的域名下,去请求http协议的域名的某个服务,并且该http域名下的服务,不仅要处理普通请求(POST、GET),还需要处理websocket请求。由于浏览器禁止https域名的内容请求http的服务,甚至嵌入子页面都禁止,因为浏览器会认为http的内容是不安全的,所以为解决该问题,研究出如下解决方案。

2 解决办法

由于浏览器禁止,但是服务器并不会禁止,所以,我在https的域名下,解析一台代理服务器,由该代理服务器去代替https去请求,再把结果返给前端。

3 开发环境

PyCharm,语言:Python3,服务框架:django

4 用到的库

pip3 install Django==1.11.3 django-cors-headers==3.2.1 dwebsocket==0.5.12 websocket==0.2.1 websocket-client==0.57.0

5 settings.py配置

# 允许访问的host为所有
ALLOWED_HOSTS = ['*'] # 配置跨域请求问题
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
)
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#'myapp.apps.MyappConfig',
# 添加当前的app
'myapp',
] MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 去除csrf校验
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

6 urls.py配置:

from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from myapp import views urlpatterns = [
path('admin/', admin.site.urls),
# 配置拦截/proxy 映射到 views.py中的方法
url(r'^proxy$',views.proxy),
]

7 views.py代码:仔细看注释

from django.shortcuts import render
from django.shortcuts import HttpResponse
import requests
from dwebsocket.decorators import accept_websocket
import logging
from websocket import create_connection
import time # 设置日志格式
LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"
fs = logging.StreamHandler()
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, datefmt=DATE_FORMAT, handlers=[fs])
# Create your views here. # 添加dwebsocket的装饰器,该装饰器会对request属性添加websocket属性
# 并添加 send()推数据 close()关闭连接 is_websocket()是否是websocket请求 等方法
@accept_websocket
def proxy(request):
# 判断请求是否是websocket
if not request.is_websocket():
# 收到的请求的格式是 https://devlab.edu.huaweicloud.com/proxy?url=http://ip:8000/senddata?model=workload-read-mostly
# 我们将这个服务部署到加了证书的服务器上,即可。
# 其中,参数url=后面是要代理的url ,我们将其截取下来,并重新请求。
url = request.get_full_path().split('url=')[1]
logging.info('proxy url : {}'.format(url))
# 进行GET请求和POST请求的分别处理
# if request.method == 'GET':
# logging.info('processing a url GET request !')
# 其中省略了将请求的 header/cookie 传递给代理请求的 header/cookie ,由于我们业务不需要这些,我就不加了。
# res = requests.get(url)
# else:
# logging.info('processing a url POST request !')
# res = requests.post(url)
# 由于我们的业务都是g GET 请求,所以就直接处理就好了
res = requests.get(url)
# 将代理请求的结果返回给真正的请求
logging.info('revc : {}'.format(res.content.decode()))
return HttpResponse(res.content.decode())
else:
# 收到的请求的格式是 wss://devlab.edu.huaweicloud.com/proxy?url=ws://ip:8000/senddata?model=workload-read-mostly
# 其中,参数url=后面是要代理的url ,我们将其截取下来,并重新请求。
url = request.get_full_path().split('url=')[1]
logging.info('proxy url : {}'.format(url))
try:
# 这里的header 必须要加上, 或者将 request中的header拿出来逐一存入list中,
# 由于request中保存的headers的格式是dict,websocket中需要的headers是list,所以需要自行转化,
# websocket的header的格式如下, 由于业务没有强制header 是什么,所以我就自己写的,但是注意,
# 需要将以下的header的内容都要补充完整,否则会报 header...相关的错误,返回200或者其他状态码的错误,
# 200在websocket是错误,在http里面是成功,需要注意一下。
header = ['Accept-Encoding: gzip, deflate',
'Connection: Upgrade',
'Pragma: no-cache',
'Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits',
'Sec - WebSocket - Version: 13',
'Upgrade: websocket',
'Access-Control-Allow-Origin: *',
'Access-Control-Allow-Headers: X-Requested-With',
'Access-Control-Allow-Methods: GET,POST,OPTIONS',
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36']
# 创建长连接/websocket
ws = create_connection(url,header=header)
# 每1秒就收一下消息
while True:
# 接收消息,如果消息中带有Finished,表示消息都接收完毕,跳出循环。
res = ws.recv()
if 'Finished' in res:
logging.info('revc : {}'.format(res))
# 该服务,即作为服务端(接收并处理请求并响应方),又做为客户端(发送请求并接收另一个服务的响应)
# 所以将代理服务推过来的结果再推给浏览器
request.websocket.send(res)
# 调试的时候,浏览器端好像收不到最后一条消息,所以我在以这种方式再发送一遍吧
# return HttpResponse(res)
# websocket 相当占用网络资源,请及时关闭,由于生产环境中,网络资源的不稳定性,
# 可能数据还没推出去,就把websocket关闭了,会造成数据的丢失。
time.sleep(5)
ws.close()
request.websocket.close()
break
if not res == None:
logging.info('revc : {}'.format(res))
# 如果有数据, 将代理服务推过来的结果再推给浏览器
request.websocket.send(res)
time.sleep(1)
# websocket 相当占用网络资源,请及时关闭,其实逻辑是走不到这里的,但是还是加上保险
ws.close()
request.websocket.close()
except BaseException as e:
logging.error(e)

8 部署

python3 manage.py runserver 0.0.0.0:8080

https://www.pythonf.cn/read/51639

HTTPS请求HTTP接口被浏览器阻塞,python实现websocket客户端,websocket服务器,跨域问题,dwebsocket,https,拦截,服务端的更多相关文章

  1. 解决前后端分离的“两次请求”引出的Web服务器跨域请求访问问题的解决方案

    在前后端分离的项目中,前端和后端可能是在不同的服务器上,也可以是Docker上,那就意味着前端请求后端Restful接口时,存在跨域情况. 后端在做了通用的跨域资源共享CORS设置后,前端在做ajax ...

  2. Chrome浏览器扩展开发系列之十五:跨域访问的XMLHttpRequest对象

    XMLHttpRequest对象是W3C的标准API,用于访问服务器资源.XMLHttpRequest对象支持多种文本格式,如XML和JSON等.XMLHttpRequest对象可以通过HTTP和HT ...

  3. chrome浏览器下用jQuery的load函数来跨域加载页面,响应状态status为(canceled)是什么情况? JSON和JSONP,也许你会豁然开朗,含jQuery用例

    http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html 问题来源:http://q.cnblogs.com ...

  4. 由一个“两次请求”引出的Web服务器跨域请求访问问题的解决方案

    http://blog.csdn.net/cnhnnyzhy/article/details/53128179 (4)Access-Control-Max-Age 该字段可选,用来指定本次预检请求的有 ...

  5. Django之jsonp跨域请求原理

    在进行网站开发的过程中经常会用到第三方的数据,但是由于同源策略的限制导致ajax不能发送请求,因此也无法获得数据.解决ajax的跨域问题有两种方法: 一.jsonp 二.XMLHttpRequest2 ...

  6. 深入理解jsonp跨域请求原理

    在进行网站开发的过程中经常会用到第三方的数据,但是由于同源策略的限制导致ajax不能发送请求,因此也无法获得数据.解决ajax的跨域问题有两种方法: 一.jsop 二.XMLHttpRequest2中 ...

  7. springboot + websocket + spring-messaging实现服务器向浏览器广播式

    目录结构 pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:// ...

  8. Web 跨域请求问题的解决方案- CORS 方案

    1.什么是跨域 跨域是指跨域名的访问,以下情况都属于跨域: 跨域现象 实例 域名不相同 www.baidu.com与www.taobao 一级域名相同,但是端口不相同 www.baidu.com:80 ...

  9. [二十七]SpringBoot 之 Restful接口的跨域请求

    什么是跨域 简单的说即为浏览器限制访问A站点下的js代码对B站点下的url进行ajax请求.比如说,前端域名是www.abc.com,那么在当前环境中运行的js代码,出于安全考虑,访问www.xyz. ...

随机推荐

  1. Spark性能调优九之常用算子调优

    1.使用mapPartitions算子提高性能 mapPartition的优点:使用普通的map操作,假设一个partition中有1万条数据,那么function就要被执行1万次,但是使用mapPa ...

  2. SQL注入-DNS注入(一)

    这篇文章相对来说比较入门,参考的文章是:https://www.jianshu.com/p/c805209244c2 0x00前言 前段时间在做盲注 分别是基于时间和基于布尔型的 说真的 这两种盲注真 ...

  3. Kubernetes K8S之Helm部署、使用与示例

    Kubernetes K8S之Helm部署.使用.常见操作与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master CentOS7.7 2 ...

  4. 【python爬虫】一个简单的爬取百家号文章的小爬虫

    需求 用"老龄智能"在百度百家号中搜索文章,爬取文章内容和相关信息. 观察网页 红色框框的地方可以选择资讯来源,我这里选择的是百家号,因为百家号聚合了来自多个平台的新闻报道.首先看 ...

  5. Java学习_Java快速入门

    Java简介 安装完JDK后,需要设置一个JAVA_HOME的环境变量,它指向JDK的安装目录.在Windows下,它是安装目录,类似: C:\Program Files\Java\jdk-15 把J ...

  6. Redis+LUA整合使用

    .前言 从本章节开始我们就开始讲解一些 Redis 的扩展应用了,之前讲的主从.哨兵和集群都相当重要,也许小公司用不到集群这么复杂的架构,但是也要了解各知识点的原理,只要了解了原理,无论什么时候是有, ...

  7. Linux 如何选择要kill掉的进程

    从网上的找了一个比较全面的如下: OOM Killer在内存耗尽时,会查看所有进程,并分别为每个进程计算分数.将信号发送给分数最高的进程.  计算分数的方法  在OOM Killer计算分数时要考虑很 ...

  8. .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 更新和删除)--学习笔记

    2.5.4 MongoDB -- 更新和删除 整体更新 更新字段 字段操作 数组操作 删除 https://docs.mongodb.com/manual/reference/operator/upd ...

  9. 每日一个linux命令6 -- rmdir

    rmdir doc 如果doc为空目录则删除,否则无法删除. rmdir -p test2/test3 递归删除空目录,首先判断test3,如果test3为空,则删除test3,此时判断test2,如 ...

  10. 2.2.1 Sqoop1的基本架构

    当用户通过shell命令提交迁移作业后,Sqoop会从关系型数据库中读取元信息,并根据并发度和数据表大小将数据划分成若干分片,每片交给一个Map Task处理,这样多个Map Task同时读取数据库中 ...