第三十九篇 vue
Posted caix-1987 - 个人博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第三十九篇 vue相关的知识,希望对你有一定的参考价值。
报告漏洞
虽然很少发现新的漏洞,但我们仍建议始终使用最新版本的 Vue 及其官方配套库,以确保你的应用尽可能地安全。
首要规则:不要使用无法信赖的模板
使用 Vue 时最基本的安全规则就是不要将无法信赖的内容作为你的组件模板。使用无法信赖的模板相当于允许任意的 JavaScript 在你的应用中执行。更糟糕的是,如果在服务端渲染时执行了这些代码,可能会导致服务器被攻击。
Vue.createApp(
template: `<div>` + userProvidedString + `</div>` // 永远不要这样做!
).mount(\'#app\')
Vue 模板会被编译成 JavaScript,而模板内的表达式将作为渲染过程的一部分被执行。尽管这些表达式在特定的渲染环境中执行,但由于全局执行环境的复杂性,Vue 作为一个开发框架,要在性能开销合理的前提下完全避免潜在的恶意代码执行是不现实的。避免这类问题最直接的方法是确保你的 Vue 模板始终是可信的,并且完全由你控制
Vue 自身的安全机制
HTML 内容
无论是使用模板还是渲染函数,内容都是自动转义的。这意味着在这个模板中:
<h1> userProvidedString </h1>
如果 userProvidedString 包含了:
\'<script>alert("hi")</script>\'
那么它将被转义为如下的 HTML:
<script>alert("hi")</script>
从而防止脚本注入。这种转义是使用 textContent 这样的浏览器原生 API 完成的,所以只有当浏览器本身存在漏洞时,才会存在漏洞。
Attribute 绑定
同样地,动态 attribute 的绑定也会被自动转义。这意味着在这个模板中:
<h1 :title="userProvidedString">
hello
</h1>
如果 userProvidedString 包含了:
\'" onclick="alert(\\\'hi\\\')\'
那么它将被转义为如下的 HTML:
" onclick="alert(\'hi\')
从而防止在 title attribute 解析时,注入任意的 HTML。这种转义是使用 setAttribute 这样的浏览器原生 API 完成的,所以只有当浏览器本身存在漏洞时,才会存在漏洞。
潜在的危险
在任何 Web 应用中,允许以 HTML、CSS 或 JavaScript 形式执行未经无害化处理的、用户提供的内容都有潜在的安全隐患,因此应尽可能避免。不过有时候一些风险或许是可以接受的。
例如,像 CodePen 和 JSFiddle 这样的服务允许执行用户提供的内容,但这是在 iframe 这样一个可预期的沙盒环境中。当一个重要的功能本身会伴随某种程度的漏洞时,就需要你自行权衡该功能的重要性和该漏洞所带来的最坏情况
注入 HTML
我们现在已经知道 Vue 会自动转义 HTML 内容,防止你意外地将可执行的 HTML 注入到你的应用中。然而,在你知道 HTML 安全的情况下,你还是可以显式地渲染 HTML 内容
1、使用模板:
<div v-html="userProvidedHtml"></div>
2、使用渲染函数:
h(\'div\',
innerHTML: this.userProvidedHtml
)
3、以 JSX 形式使用渲染函数:
<div innerHTML=this.userProvidedHtml></div>
警告
用户提供的 HTML 永远不能被认为是 100% 安全的,除非它在 iframe 这样的沙盒环境中,或者该 HTML 只会被该用户看到。此外,允许用户编写自己的 Vue 模板也会带来类似的危险。
URL 注入
在这样一个使用 URL 的场景中:
<a :href="userProvidedUrl">
click me
</a>
如果这个 URL 允许通过 javascript: 执行 JavaScript,即没有进行无害化处理,那么就会有一些潜在的安全问题。可以使用一些库来解决此类问题,比如 sanitize-url,但请注意:如果你发现你需要在前端做 URL 无害化处理,那你的应用已经存在一个更严重的安全问题了。任何用户提供的 URL 在被保存到数据库之前在应该先在后端做无害化处理。这样,连接到你 API 的每一个客户端都可以避免这个问题,包括原生移动应用。另外,即使是经过无害化处理的 URL,Vue 也不能保证它们指向安全的目的地
样式注入
<a
:href="sanitizedUrl"
:
>
click me
</a>
我们假设 sanitizedUrl 已进行无害化处理,它是一个正常 URL 而非 JavaScript。然而,由于 userProvidedStyles 的存在,恶意用户仍然能利用 CSS 进行“点击劫持”,例如,可以在“登录”按钮上方覆盖一个透明的链接。如果用户控制的页面 https://user-controlled-website.com/ 专门仿造了你应用的登录页,那么他们就有可能捕获用户的真实登录信息。
你可以想象,如果允许在 <style> 元素中插入用户提供的内容,会造成更大的漏洞,因为这使得用户能控制整个页面的样式。因此 Vue 阻止了在模板中像这样渲染 style 标签:
<style> userProvidedStyles </style>
为了避免用户的点击被劫持,我们建议仅在沙盒环境的 iframe 中允许用户控制 CSS。或者,当用户控制样式绑定时,我们建议使用其对象值形式并仅允许用户提供能够安全控制的、特定的属性,就像这样:
<a
:href="sanitizedUrl"
:
>
click me
</a>
JavaScript 注入
我们强烈建议任何时候都不要在 Vue 中渲染 <script>,因为模板和渲染函数不应有其他副作用。但是,渲染 <script> 并不是插入在运行时执行的 JavaScript 字符串的唯一方法。
每个 HTML 元素都有能接受字符串形式 JavaScript 的 attribute,例如 onclick、onfocus 和 onmouseenter。绑定任何用户提供的 JavaScript 给这些事件 attribute 都具有潜在风险,因此需要避免这么做。
警告
用户提供的 JavaScript 永远不能被认为是 100% 安全的,除非它在 iframe 这样的沙盒环境中,或者该段代码只会在该用户登陆的页面上被执行
有时我们会收到漏洞报告,说在 Vue 模板中可以进行跨站脚本攻击 (XSS)。一般来说,我们不认为这种情况是真正的漏洞,因为没有切实可行的方法,能够在以下两种场景中保护开发者不受 XSS 的影响。
1、开发者显式地将用户提供的、未经无害化处理的内容作为 Vue 模板渲染。这本身就是不安全的,Vue 也无从溯源。
2、开发者将 Vue 挂载到可能包含服务端渲染或用户提供内容的 HTML 页面上,这与 #1 的问题基本相同,但有时开发者可能会不知不觉地这样做。攻击者提供的 HTML 可能在普通 HTML 中是安全的,但在 Vue 模板中是不安全的,这就会导致漏洞。最佳实践是:不要将 Vue 挂载到可能包含服务端渲染或用户提供内容的 DOM 节点上。
最佳实践
最基本的规则就是只要你允许执行未经无害化处理的、用户提供的内容 (无论是 HTML、JavaScript 还是 CSS),你就可能面临攻击。无论是使用 Vue、其他框架,或是不使用框架,道理都是一样的。
除了上面为处理潜在危险提供的建议,我们也建议你熟读下面这些资源:
1、HTML5 安全手册
2、OWASP 的跨站脚本攻击 (XSS) 防护手册
接着你可以利用学到的知识,来审查依赖项的源代码,看看是否有潜在的危险,防止它们中的任何一个以第三方组件或其他方式影响 DOM 渲染的内容。
后端协调
类似跨站请求伪造 (CSRF/XSRF) 和跨站脚本引入 (XSSI) 这样的 HTTP 安全漏洞,主要由后端负责处理,因此不是 Vue 职责范围内的问题。但是,你应该与后端团队保持沟通,了解如何更好地与后端 API 进行交互,例如在提交表单时附带 CSRF 令牌
服务端渲染 (SSR)
在使用 SSR 时还有一些其他的安全注意事项,因此请确保遵循我们的 SSR 文档给出的最佳实践来避免产生漏洞
第三十九篇 matplotlib模块
matplotlib模块
绘图库,可以创建常用的统计图(条形图、箱型图、折线图、散点图和直方图)
bar() 条形图
# 由于该模块不识别中文,所以我们需要导入一个中文简体字文件
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
font = FontProperties(fname='B:\\msyh.ttc') # 在文件B中找字体文件
# 修改背景为条纹
plt.style.use('ggplot')
classes = ['1班','2班','3班','4班'] # 班级
classes_index = range(len(classes)) # 班级索引
# print(type(classes_index)) <class 'range'>
# print(list(classes_index)) [0, 1, 2, 3]
student_amounts = [43, 55, 60, 36] # 各班人数
# figure中的参数figsize 控制画布大小
# 生成画布
fig = plt.figure() # fig:打扮 figure:图形,画像
# 设置画布
# 1,1,1表示一张画布切割成1行1列共一张图的第1个;
# 2,2,1表示一张画布切割成2行2列共4张图的第一个(左上角)
axl = fig.add_subplot(1,1,1) # subplot:陪衬 axl:光束轴
# 生成柱状图,bar:条、棒
axl.bar(classes_index,student_amounts,align='center',color='blue')
# 在底部生成x轴
axl.xaxis.set_ticks_position('bottom') #bottom:底部 xaxis:横轴
# 在左边生成y轴
axl.yaxis.set_ticks_position('left') # left:左边 yaxis:纵轴
# 将班级文字放在班级索引上
# xticks:设置柱的文字说明 #ticks:十字叉
plt.xticks(classes_index,classes,rotation=0,fontsize=13,fontproperties=font)
# x轴上放班级
plt.xlabel('班级',FontProperties=font,fontsize=15)
# y轴上放学生人数
plt.ylabel('学生人数',FontProperties=font,fontsize=15)
# 画布标题
plt.title('班级-学生人数',FontProperties=font,fontsize=15)
# 展示图形
plt.show()
hist() 直方图
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
font = FontProperties(fname='B:\\msyh.ttc')
import numpy as np
plt.style.use('ggplot')
# 自定义两个值
mu1,mu2 = 50,100
# 用于改造随机数,让它符合正态分布的需要
sigma = 10
# 构造均值为50的符合正态分布的数据
x1 = mu1 + sigma*np.random.randn(10000)
x2 = mu2 + sigma*np.random.randn(10000)
# 生成画布
fig = plt.figure()
# 设置画布
# 将画布分成一行两列,取第一部分画图(也就是在左边画)
axl1 = fig.add_subplot(121)
#bins=50表示每个变量的值分成50份,即会有50根柱子
axl1.hist(x1, bins=50, color='darkgreen') # 深绿
# 将画布分成一行两列,取第二部分画图(也就是在右边画)
axl2 = fig.add_subplot(122)
axl2.hist(x2, bins=50, color='orange') # 橙色
# 大标题
fig.suptitle('两个正态分布', fontproperties=font, fontweight='bold', fontsize=15)
# 第一个图的标题
axl1.set_title('绿色的正态分布', fontproperties=font)
# 第二个图的标题
axl2.set_title('橙色的正态分布', fontproperties=font)
# 展示
plt.show()
plot() 折线图
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
font = FontProperties(fname='B:\\msyh.ttc')
plt.style.use('ggplot')
import numpy as np
from numpy.random import randn
# 随机数种子,固定一个变量的随机数永远不变,只能对同一个变量起作用
np.random.seed(1)
# 使用numpy的累加和,保证数据取值范围不会在(0,1)内波动
# 定义足够的一维数组,每个数组都用于生成一条折线图
plot_data1 = randn(40).cumsum()
plot_data2 = randn(40).cumsum()
plot_data3 = randn(40).cumsum()
plot_data4 = randn(40).cumsum()
# 通过数据绘制折线图
plt.plot(plot_data1, marker='o', color='red', linestyle='-', label='红实线')
plt.plot(plot_data2, marker='x', color='orange', linestyle='--', label='橙虚线')
plt.plot(plot_data3, marker='*', color='yellow', linestyle='-.', label='黄点线')
plt.plot(plot_data4, marker='s', color='green', linestyle=':', label='绿点图')
# label :标签,就是标注
# loc = 'best'表示给label(标签)自动选择最好的位置
plt.legend(loc='best',prop=font)
plt.show()
scatter() 散点图+直线图
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
font = FontProperties(fname='B:\\msyh.ttc')
# 设置画布背景为网格
plt.style.use('ggplot')
import numpy as np
from numpy.random import randn
# 创建一个一维数组
x = np.arange(1,20,1)
# 拟合一条水平散点线
# 合并两个一维数组,得到一个新的数组,用于绘图
np.random.seed(1) # 随机数种子
y_linear = x+10*np.random.randn(19) # 随机数组
# 拟合一条x2的散点线
# 第二个用于散点绘图和直线绘图的数组
y_quad = x**2+10*np.random.randn(19)
# 生成画布
fig = plt.figure()
# 设置画布
# 将画布分成一行两列,在第一个部分作图
ax1 = fig.add_subplot(121)
# 生成散点图,x为横坐标数据,y_linear和y_quad为纵坐标数据
plt.scatter(x, y_linear, s=30, color='r', label='蓝点')
plt.scatter(x, y_quad, s=100, color='b', label='红点')
# 第二部分画直线图
ax2 = fig.add_subplot(122)
# 生成直线图(折线图),x为横坐标数据,y_linear和y_quad为纵坐标数据
plt.plot(x, y_linear, color='r')
plt.plot(x, y_quad, color='b')
# 限制x轴和y轴的范围取值
plt.xlim(min(x)-1, max(x)+1)
plt.ylim(min(y_quad)-10, max(y_quad)+10)
# 画布大标题
fig.suptitle('散点图+直线图', fontproperties=font, fontsize=20)
# 左画布标题
ax1.set_title('散点图', fontproperties=font)
# 左画布图例,指label(标题),去掉的话将不显示
ax1.legend(prop=font)
# 右画布标题
ax2.set_title('直线图', fontproperties=font)
# 展示
plt.show()
以上是关于第三十九篇 vue的主要内容,如果未能解决你的问题,请参考以下文章
Python之路(第三十九篇)管道进程间数据共享Manager