自从大二初次接触前端以来,一直都有记markdown笔记的习惯.又因为掘金最近有一个活动.所以开了这个专栏。我会写一些业务相关的小技巧和前端知识中的重点内容之类的整理一下发上来。难免有点地方不够细致。欢迎大家指教
这篇文章 是我 学习 前端以来可以用来性能优化的前端安全相关 知识点 和 一些 个人的见地
3.1.常见Web攻击
3.1.1 XSS
跨站脚本攻击(solution:函数过滤+dom的过滤)
将恶意script代码植入页面中,需要对输入过滤来防御,或者服务器设置set-cookie来修改客户端cookie的httpOnly或secure属性,如果设置httpOnly那么js脚本就不能访问cookie(不能通过脚本直接获取cookie),如果设置secure,那么只能https发送cookie(Cookie 是否仅仅通过安全的 HTTPS 连接传给客户端)
3.1.2 CSRF
跨站请求伪造(solution:双token cookies和请求头header里面都有token)
诱导用户进入第三方网站从而获取原网站保存的凭证,需要同源策略来防御,例如验证码、token、检查http头部的Referer属性值(Referer属性值为实际发送请求的网址)
3.1.3 SQL注入
将恶意的sql语句插入输入参数中,在后台解析执行,需要严格检查输入类型和格式 点击劫持:通过透明的iframe或图片覆盖,让用户误点击,可以设置响应头
3.1.4 双包危险
go
双包危险(cjs和esm混用)
1.instance of这个函数识别不到
2.添加属性可能识别不到
语法混用同一个环境会
3.2.前端性能优化
3.2.1 常用方法
-
低请求量:合并资源(例如webpack抽离公共模块),gzip压缩,懒加载(路由懒加载、UI框架按需引入、图片表格懒加载)
-
加快请求速度:DNS预解析(字节是这样做的:
ini<link rel="dns-prefetch" href="//sso.douyin.com">
)、CDN分发、资源并行加载
-
合理使用缓存:webStorage(localStorage, sessionStorage), HTTP缓存,Service Worker(利用Web Worker离线缓存资源)
-
渲染:JS/CSS优化
3.2.2 常用指标
lua
--1.首屏渲染时间(fcp:利用permance这个api来实现fcp。response_start-navigation_start --2.后面全部加载完(ra:reponsend-responstart)
--3.fid:首次输入延迟。
--4.lighthouse或者人工判断
--5.
ttl(界面交互时间)| time to interactive
lcp(largest Contentful Paint(最大内容渲染时间) )
3.2.3 指标函数
3.2.3.1 fcp(getEntries('paint'))
这个是第一个渲染的element进行绘制
ini
const fcp = performance.getEntries('paint').filter(entry => entry.name == 'first-contentful-paint')[0].startTime;
3.2.3.2 fp(getEntries('paint'))
对第一个渲染的像素点进行绘制
ini
const fp = performance.getEntries('paint').filter(entry => entry.name == 'first-paint')[0].startTime;
3.2.3.3 dcl
文档被加载 DOMContentLoaded
:HTML文档的加载与解析(一般比load 块)
performance.timing.domContentLoadedEventStart - performance.timing.fetchStart
3.2.3.4 load
资源被加载
performance.timing.loadEventEnd - performance.timing.fetchStart
3.3.polyfill
本质是一块代码,为兼容性有问题的浏览器提供它不支持的功能。使用时只需要script标签引入即可。
3.4.页面白屏的解决办法 骨架屏
资源预加载 代码分割并行加载(webpack) 路由按需加载,UI框架按需引入
3.6 gzip 开启两种
bash
注意一下 webpack的compression-webpack-plugin要安装上。打包的时候生成gz为结尾的文。件仅仅是生成gzip文件,浏览器访问并不会自动识别,也不能直接引入gzip文件,需要服务器端开启gzip访问权限。由于动态压缩会占用浏览器资源,所以我们可以提前gz压缩
//第一种是当用户请求文件时压缩文件,显然压缩文件需要耗费 CPU 和内存,而且是每次访问时都要重新压缩一次。
//另一种是当用户请求文件时,直接访问文件旁边的同名 .gz 文件,显然这不需要耗费多少 CPU 和内存。如果没有同名文件,再去做压缩。
nginx
//开启gzip访问
gzip on;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
#由于nginx的压缩发生在浏览器端而微软的ie6很坑爹,会导致压缩后图片看不见所以该选
项是禁止ie6发生压缩
gzip_disable "MSIE [1-6].";
#如果文件大于1k就启动压缩
gzip_min_length 1k;
#以16k为单位,按照原始数据的大小以4倍的方式申请内存空间,一般此项不要修改
gzip_buffers 4 16k;
#压缩的等级,数字选择范围是1-9,数字越小压缩的速度越快,消耗cpu就越大
gzip_comp_level 2;
#引导的在/etc/nginx/conf.d目录下所有后缀为.conf的子配置文件
include /etc/nginx/conf.d/*.conf;
查看一个网站是否使用gzip压缩,可以通过控制台查看打开响应头中的Content-Encoding选项,如果出现gzip,则开启成功
3.7 数据埋点
数据埋点上报统一的入口:可以监听defineproerty的get方法
3.8 安全性https script | meta | js
3.8.1 content-security-policy
3.8.1.1 大厂示例
字节官网策略:只是上报数据,并没有在reponse中直接中限制策略
kotlin
content-security-policy-report-only: frame-ancestors https://tcs.bytedance.net https://*.douyin.com;
default-src 'self' data: blob: 'unsafe-inline' 'unsafe-eval' *.amemv.com ;
img-src 'self' blob: data: android-webview-video-poster: 'unsafe-inline' 'unsafe-eval' *;
connect-src 'self' wss: *;
font-src 'self' *.bytedance.com *.bytescm.com;
media-src 'self' blob: data: 'unsafe-inline' 'unsafe-eval' *.ixigua.com *.snssdk.com *.pstatp.com *.douyin.com ;
report-uri https://i.snssdk.com/log/sentry/v2/api/slardar/main/?ev_type=csp&bid=douyin_web;
report-to main-endpoint;child-src 'self' data: blob: *.bytedance.com live.douyin.com *
3.8.1.2 基本示例
只允许从指定的源来加载,减少和报告 XSS 攻击
xml
--1.content-security-policy:内容安全策略
<meta http-equiv="content-security-policy" content=" default-src 'self'">
<meta http-equiv="content-security-policy-report-only" content="策略">
--2.如果 HTTP 头与 Meta 定义同时存在,则优先采用 HTTP 中的定义。
--3.报告示例
Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi
--3.禁止示例
<!-- 不能分成两行写,不然报错。这些东西都是字面意思-->
<meta http-equiv="Content-Security-Policy" content="default-src 'self';script-src 'unsafe-inline' ;style-src https://unpkg.com 'unsafe-inline' ; font-src https://unpkg.com">
<!--所有http变成https链接 -->
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
3.8.2 strict-transport-security
(reponse)
3.8.2.1 大厂示例
ini
字节官网策略:strict-transport-security: max-age=31536000;
3.8.2.2 基本示例
ini
--1.全称是https strict-transport-security:严格安全传输
如果在有效期内用http访问这个地址,那么会返回307重定向
示例:strict-transport-security:max-age=86400 (秒)
--2.有个问题是你在https设置这个请求是有效的,但是你要是在http设置这个请求头完全无效
<meta http-equiv="strict-transport-security" content="max-age=86400">
3.8.3 x-frame-options
字节官网策略:x-frame-options: DENY
可以不允许别人用iframe加载你的界面
css
一般就三个值:
X-Frame-Options:DENY(不允许使用)
SAMEORIGIN (同源使用)
frame-ancestors b.com (允许xx嵌套)
frame-src (允许加载xx)
3.8.4 nonce
script上的js完整性和安全性校验
css
--1.reponse返回的时候的header值:Content-Security-Policy: script-src 'nonce-Ef'
--2.<script nonce="nonce-Ef" src="./hello.js"></script>
3.8.5 integrity
常用于cdn上面
3.8.5.1 大厂示例
字节把这里进行了打包,因此我们看不到。
common-monitors里面有integrity这个属性
3.8.5.2 例子
bash
--1.可以通过 https://www.srihash.org/ 生成hash值
--2.然后<script type="module" src="app.js" integrity="sha256"></script> 填进去hash值
3.8.6 crossorigin
是否跨域
3.9 学习大厂实操
这个小结通过查看大厂官网的header查看有哪一些简单的优化手段.下面这些大厂meta的name和description都是有的
3.9.1 字节
css
1.CSP安全头-content-security-policy-report-only+report-uri
2.HSTS安全头:<meta http-equiv="strict-transport-security" content="max-age=86400 ">
3.x-frame-options:不允许别人用iframe加载你的界面
4.link的rel属性用dns-prefetch预加载
5.用了CSP安全头但是没用他最常见的content-security-policy而是用x-xss-protection进行了替换。x-xss-protection: 1; mode=block对于CSP的好处是可以对那些暂时不支持CSP的浏览器进行保护。当检测到xss脚本的时候,页面会停止加载
6.script用了 crossorigin,nonce,integrity 做安全
7.甚至js中还有roles,aria-checked属性
8.tdk
总结
1.x开头的reponse头:x-xss-protection,x-frame-options
2.安全的reponse头:STS ,CSP
3.安全的js:dns-prefetch, crossorigin,nonce(跟csp一起用),integrity(hash)
4.人文:roles,aria-checked
3.9.2 拼多多
总结:稍逊一筹
bash
1.没有用CSP,HSTS
1.link的rel属性用preload
3.script用了crossorigin,async
4.meta的cache-control 和 pragma 和 expires
5.tdk
3.9.3 CVTE
总结:.........
1.tdk
2.x-frame-options
3.甚至https的官网显示是不安全的
3.9.4 gitee
总结:基本没有做安全性js的设置,但是有一些点确实是很有意思的
ini
--1.meta
--1.1 x-dns-prefetch-control | viewport(最大最小都有设置) | X-UA-Compatible(设置成ie的)| google(class="notranslate" , 这一点非常有意思。只要给不想被翻译的地方添加class的类名 notranslate也可以做到)| Cache-control(no-cache) Expires(0)
--2 dns-prefetch | | google
--3.script :async defer="defer"
3.9.5 谷歌
总结:
ini
--1.jsmodel="data" | jsname="data" | jsaction
3.9.6 stackoverflow
bash
--1.og 和 twitter开头的一系列属性
https://developers.facebook.com/docs/plugins/share-button/#example
https://www.nousbuild.org/codeu/custom-share-link/
og:title | og:type | og:url | og:image
基于Open Graph 的东西,分享出去的时候能够按照特定方式进行解析。目前企业微信上已经实现
--2.script 的 async
--3.http-equiv (利于开发人员增加实验性功能) | 令牌相等可以开启新功能 , 有Popover API,WebGL 2,Picture-in-Picture | App Dark Mode 等新功能
http-equiv 的 origin-tria:https://developer.chrome.com/origintrials/#/trials/active
3.9.6 twitter
ini
--1.link rel = preconnect | dns-prefetch | preload
--2. meta name =google-site-verification
--3. facebook-domain-verification 广告的权力 和 链接的权利
--4.apple-mobile-web-app-title
--5.一堆og
--6.Onion-Location content="xxxx.og"
3.10 性能优化示例
3.10.1 html meta头示例
xml
<!DOCTYPE html>
<html lang="en">
<!-- W
从字节学到的
1.CSP安全头-content-security-policy-report-only+report-uri
2.HSTS安全头:<meta http-equiv="strict-transport-security" content="max-age=86400 ">
3.x-frame-options:不允许别人用iframe加载你的界面
4.link的rel属性用dns-prefetch预加载
5.用了CSP安全头但是没用他最常见的content-security-policy而是用x-xss-protection进行了替换。x-xss-protection: 1; mode=block对于CSP的好处是可以对那些暂时不支持CSP的浏览器进行保护。当检测到xss脚本的时候,页面会停止加载
6.今日头条的官网用了descripton和keywords做seo
7.script用了 crossorigin,nonce,integrity 做安全
-->
<head>
<!-- 设置文档的编码为 utf-8 -->
<meta charset="ISO-8859-1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 1.seo优化:搜索引擎有一些会搜索 content,使用逗号分隔,关键词,name不能变 -->
<meta name="keywords" content="HTML5,css,js">
<meta name="description" content="这是meta的测试">
<!-- 允许抓取本页和跟踪链接,noindex和nofollow是不允许抓取链接和跟踪链接 -->
<meta name="robots" content="index,follow">
<!--
viewport是移动端页面渲染的容器,手机浏览器把页面放在这个虚拟的窗口里面,通常这个viewport比实际宽度宽
width可以给一个指定数值,但是会变得不好 -->
<!-- <meta name="viewport" content="width=device-width, initial-scale=10.0"> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 2.CSP安全策略示例 ,不能分成两行写,不然报错。这些东西都是字面意思。-->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self';script-src 'unsafe-inline' ;style-src https://unpkg.com 'unsafe-inline' ; font-src https://unpkg.com">
<!-- 像下面这样子设置了之后,只有在 script 标签内带有相同 nonce 值的脚本才能执行。 -->
<!-- <script nonce="nonce-Ef" src="./hello.js"></script> -->
<!-- <meta http-equiv="Content-Security-Policy" content="script-src 'nonce-Ef'"> -->
<!--所有http变成https链接 -->
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
<!-- 3.STS安全示例 -->
<meta http-equiv="strict-transport-security" content="max-age=86400 ">
<Meta http-equiv="Window-target" Content="_top">
<title>Meta头示例</title>
<!-- 常用头设置 -->
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="expires" Content="86400">
<!-- 这是2秒后跳转,如果要2秒刷新一次我们把后面的url去掉就好了 -->
<!-- <meta http-equiv="refresh" content="2 url='http://hi.baidu.com/tesalo/'" /> -->
<!--
这里可以用来进行es6的测试
Content-Security-Policy: script-src 'nonce-Ef';
<script type="module" src="app.js" integrity="sha256"></script>
<script nomodule src="classic-bundle.js"></script>
-->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<style>
body {
word-wrap: break-word;
}
</style>
<div role="checkbox" aria-checked="checked">111</div>
<form>
<input type="text" name="username" id="" tabindex="1" />
<a href="www.baidu.com" tabindex="-1">注册账号</a>
<input type="password" name="password" tabindex="2" />
</form>
<script>
// 易错:1.get 请求不能有body
// 2.第一次返回的结果是一个promise或者是respnse对象
let datat = fetch("http://127.0.0.1:5501/docs/know/img/data.json", {
method: 'GET',
headers: {
// 'Content-Type': 'application/json',
},
mode: "cors",
credentials: "include",
cache: "default"
}).then(res => {
let ceshi = res.json()
ceshi.then((result) => {
console.log(result)
})
})
</script>
</body>
</html>
3.10.2 合并前端请求 | 请求压缩
scss
--1.nginx里面合并前端请求 nginx-http-concat(tengine)
--2.缓存
--3.请求数 | 应用优化 | 动静结合
const user = await userFetch();
const product = productFetch();
变成
const [user , products] = await Promise.allSettled([
userFetch(),productFetch()
])
function handle(data){
if (user.status == 'rejected'){
log(data)
}
}
handle(user)
--4.资源供给(cdn) 请求分流 压缩传输:nginx加上lvs f5的系统
ini
--1.js压缩请求
<script src="/js/extend.js,jquery-1.12.4.js,jquery.min.js,validform_v5.3.2.js,wechatLink-1.1.js"></script>
--2. promise请求合并
merge=false
zGet (url, param, merge=false)
// 检查是否命中缓存中的promise如果有返回命中,不再发出请求
checkPromise(url,param)
//然后看一下有没有相同的promise(key来控制)
if(merge && cachePromise){
return cachePromise
}
--3.nginx
nginx-http-concat(tengine)-(使用的时候多传一个参数merge 表示是否使用并发合并的功能)
--4.结果合并
var requestNum = 3;//声明请求数,用于记录请求完成计数,每完成一个请求则减1,直到为0;
成功的时候
//如果请求记录为0,则触发所有请求完成的监听回调
//此请求完成后,记录数减1
//结果进行可靠地合并
--5.分片并发上传
let arr= [
[axios(),axios(),axios()],
[axios(),axios(),axios(),axios()],
[axios(),axios(),axios()],
]
let result = []
Promise.all(arr[0]).then(res=>{
result = result.concat(res)
return Promise.all(arr[1])
}).then(res=>{
result = result.concat(res)
return Promise.all(arr[2])
}).then(res=>{
result = result.concat(res);
console.log(result);
})
--6.直接promise.allsettle
3.11 长列表性能优化
我们要知道界面渲染的瓶颈主要在 dom的渲染
我们有三种方法。
3.11.1 虚拟列表
diff
--1.注意一下,虚拟列表有一个点。就是有苹果系统会有虚拟滚动条不生效的bug。
--2.知识点:主要就是判断当前可观测视口的数据长度来进行渲染
3.11.2 大列表分块渲染
ini
--1.知识点:一进入界面的时候我们可以一直渲染数据
//可以扔到table界面
blockLoading(originData, that) {
let total = originData.length;
// 一次插入 50 条
let once = 50;
//每条记录的索引
let index = 0;
//循环加载数据
function loop(curTotal, curIndex, data) {
if (curTotal <= 0) {
return false;
}
//每页多少条 少于once 我们就取值
let pageCount = Math.min(curTotal, once);
window.requestAnimationFrame(function () {
for (let i = curIndex; i < curIndex + pageCount; i++) {
// 这里运行我们的逻辑
that.$set(that.lastData, i, data[i]);
}
loop(curTotal - pageCount, curIndex + pageCount, data);
});
}
loop(total, index, originData);
}
3.11.2 前端手动分页
diff
--1.知识点:直接分页
3.12 防盗链
3.12.1 nginx
perl
原理是利用request的请求头refer做判断然后指定的才进行放行
location ~*.(png|jpg|gif){
#放行白名单
valid_referers 192.168.200.222 *.example.com example.*;
if ($invalid_referer){
return 403;
}
rewrite ^/ https://blog.csdn.net/;
break;
}
3.13 cookie隔离
diff
--1.cookie隔离指的是用别的域名来进行静态资源的存储
--2.利用浏览器跨域的操作的时候不会带有cookie数据,这样就可以减少请求头的大小。
3.14 f12中的 字符画
3.14.1 console.log个性化打印
arduino
console.log('飞鸟%c慕鱼%c博客' ,'color:red','color:blue');
console.log("公司诚聘前端工程师\n%c 简历投递地址 %c http://www.badu.toudi.com ", "color:blue;font-weight:bold;","color:red");
less
let a = "a/b/c/d"
// /g全局替换 不然只会替换第一个
a ="a/b/c/d";
var b = a.replace(///g,"\");
a =`a\b\c\d`;
console.log(String.raw`${a}`)
3.14.2 生成字符画
markdown
使用网站patorjk.com/来生成自己的字符画,然后进行转义 把所有 \ 变成\ 。然后在通过代码包装输出到控制台。
--1.String.raw 返回转义前的字符串 (cider面试的标准答案)
let a= String.raw`
___________.__ __ .__
_ _____/| | ____ ____ _/ |_ _______ ____ | | __ __ ___ ___
| __)_ | | _/ __ \ _/ ___\ \ __\_ __ \ / _ \ | | | | \ / /
| | |__\ ___/ \ ___ | | | | /( <_> )| |__| | / > <
/_______ /|____/ ___ > ___ > |__| |__| ____/ |____/|____/ /__/_ \
/ / / /
`
console.log(a)
let a={id:"\15",name:"dd"}
String.raw`${a.id}`
String.raw`\15` String.raw`\15`
console.log(`
%c
__________.__ __ .__
\_ _____/| | ____ _____/ |________ ____ | | __ _____ ___
| __)_ | | _/ __ \/ ___\ __\_ __ \/ _ \| | | | \ \/ /
| \| |_\ ___| \___| | | | \( <_> ) |_| | /> <
/_______ /|____/\___ >___ >__| |__| \____/|____/____//__/\_ \
\/ \/ \/
`,"color:red")
st
3.15 webview 性能优化
java
h5做性能优化,例如代码质量,js打包,css打包,cdn加速
app初始打开的时候,是不会不会初始化浏览器内核。
--1.初始化一个全局的webview(省去了70-700ms),访问webview直接使用webview。
--2.用native 开始网络请求数据,然后页面开始时候,可以向native获取代理请求(数据请求和webview的native并行)
3.16 webpack常见优化手段
前端性能优化分为两类:一类是文件加载更快、另一类是文件渲染更快
3.16.1 代码分析
arduino
//1.BundleAnalyzer 分析打包大小
//2.speedmeasure:分析加载速度
3.16.2 编译速度
arduino
//1.threadloader-第一次编译的时候慢一点。后面贼快
//2.Terser 也可以在编译的时候
//3.swc loader增加ast 解析速度
3.16.3 加载速度
arduino
--1.体积压缩
//1.js压缩:terser压缩-原理-1.删除注释,空格,换行符 2.变量名压缩 3.提前计算4.console.log 去除
//2.image压缩:imagemin-原理-1.例如png会把24位的图片信息压缩成8位的信息
//3.css压缩:cssnano+postcss-原理-1.删除注释,空格 2.变量名压缩
//4.js压缩:还有一个压缩是利用webpack的压缩optimization(优化器)进行代码分包。
//常用的是chunkIds(算法:可以选择named-短期缓存和detaerministic-长期缓存)和splitChunks(主要是里面的cacheGroups verndor的test-正则匹配名字和minChunk-最小引用数 一般来说呢.多引用的会专门分包)
--2.
//1.使用长连接
//2.雪碧图/精灵图
//3.节流防抖
3.16.4 渲染速度
css
1.缓存(HTTP缓存、本地缓存、Vue的keep-alive缓存等)
2.提前渲染:ssr服务器端渲染
3. 避免渲染阻塞:CSS放在HTML的head中 JS放在HTML的body底部
4.懒加载
5.对dom查询进行缓存、将dom操作合并、使用减少重排的标签
3.16.5 简单口诀
bash
包 后套套,包 前 cp,中间gls。最后acg
包后压缩ttcnb treeshaking terser cache nano(css体积)imagemin-webpack browlist
中间性能:glspf prefetch gzip split跟cachegroup一起用 loader
包前tscpd cache swc thread pnpm dllplugin
分析 speedmeasure bundleanalyse
3.17 优化数据结构
3.17.1 背景
arduino
enum offConfigStatus {
'未开始',
'下架申请中',
'通过下架 ',
'拒绝下架',
}
// 上下线状态
enum appConfigStatus {
'未上线' = 1,
'已上线',
}
// 审核状态
enum reviewConfigStatus {
'创建中' = 1,
'待审核',
'审核未通过',
'审核已通过',
}
export { offConfigStatus, appConfigStatus, reviewConfigStatus };
类似是这样的数据结构,但是不利于维护
3.17.2 映射
typescript
type EnumTransType<T, type> = {
[K in T]: type;
};
export type FormType = 'add' | 'edit';
export interface AppCommonInfo {
auditStatus: string; // 应用审核状态s
packageName: string; // 包名
latestVersion: string; // 最新版本号s
updateTime: string; // 最后更新时间
}
export enum ReviewStatusEnum {
created = 1,
willApproved,
unApproved,
Approved,
}
export enum OffStatusEnum {
notStarted = 0,
underRemovalApp,
appRemovedSuccessfully,
appRemovedRejected,
}
// 上下线状态
export enum AppStatusEnum {
notOnline = 1,
online,
}
export type ReviewStatusDataType = EnumTransType<
keyof typeof ReviewStatusEnum,
string
>;
export type OffStatusType = EnumTransType<keyof typeof OffStatusEnum, string>;
export type AppStatusType = EnumTransType<keyof typeof AppStatusEnum, string>;
const.ts
javascript
import {
AppStatusType,
OffStatusType,
ReviewStatusDataType,
} from '@/types/manageCenter.d';
export const ReviewStatusData: ReviewStatusDataType = {
created: '创建中',
willApproved: '待审核',
unApproved: '审核未通过',
Approved: '审核已通过',
};
export const AppStatus: AppStatusType = {
notOnline: '未上线',
online: '已上线',
};
export const OffStatus: OffStatusType = {
notStarted: '未开始',
underRemovalApp: '下架申请中',
appRemovedSuccessfully: '通过下架',
appRemovedRejected: '拒绝下架',
};
// AppStatusEnum
{
"1": "notOnline",
"2": "online",
"notOnline": 1,
"online": 2
}
// AppStatus 状态如下
{
"notOnline": "未上线",
"online": "已上线"
}
3.18 授权加密算法
一般来说用 jsencrypt 和 croto js
3.18.1 jwt
1.JWT生成的Token字符串需要客户端手动存储在localStorage或sessionStorage中。再次请求时,客户端需要将Token放在请求头的Authorization字段中。 2. jwt是Json Web Token的缩写,它的结构分为三个部分:header(签名的算法).payload(过期时间).signature(用户自己定义的字段),两两之间用【.】分隔。
3.18.2 OAuth2
css
OAuth2 就是一种授权机制。类似于我给外卖小哥一个临时的门禁卡.这个思想广泛用在sso上面.
例如前后端的授权码,例如a跳转到b请求b授权用户数据(现在的微信登陆和支付宝登陆就是这样),跳转时会返回一个授权码。令牌的使用一般是header加上一个Authorization。一般我们会有两个令牌,一个用来正常使用,一个用来更新令牌
3.18.3 AES | RSA
- (AES)对称加密:加密密钥和解密密钥相同(padding 和 key)---(一把钥匙)
- (RSA)非对称加密:加密密钥和解密密钥不相同(原理是 大质数相乘十分容易,但是对其进行因式分解却十分麻烦 | 公钥加密明文,然后把加密的明文发给服务器)----虽然说好像很麻烦,但是代码却很简单(两把钥匙)
- 后端生成publicKey与privateKey
- 后端返回publicKey给前端
- 前台使用publicKey给 某一个标识
project-key
之类的 加密 - 后端使用publicKey与pvivateKey进行解密。
最佳实践:数据加密采用AES,而把AES的加密秘钥用RSA加密,这样兼顾速度及安全性
3.19 运维上的性能优化
cache-control
- private:表明响应只能浏览器缓存 ,服务器不能缓存它
- no-cache:强制协商缓存 ,no cache 是禁止本地缓存.下一次
- no-store:不使用任何缓存
- max-age=0 针对这一次响应 | 后端设置了 20就是这20s你别来烦我,前端只有0才可以一直进行304的请求,不然就一直是 from cache
3.19.1 缓存
css
磁盘缓存和内存缓存(强缓存-cache-control):
memory cache>disk cache
1.大东西,css会被存放在磁盘中。preload prefetch也是在磁盘
2.memory里面是经常用的比如js,img
协商缓存 304
第一次200,前端后端 第二次不变就是304.
| | 前端 | 后端 | nginx | 结果 |
|---------------|-----------|------------|------------|---------------------------------------------|--------------------|
| cache-control | no-cache | max-age=20 | | 每次都会真正请求 返回200,前端在这里的优先级最高 |
| cache-control | max-age=0 | no-store | | 每一次都是200 |
| cache-control | max-age=0 | max-age=20 | 0 | | 资源变化返回200,不然304 |
| cache-control | max-age=0 | no-cache | | 资源变化返回200,不然304 |
| cache-control | max-age=3 | max-age=5 | max-age=20 | 5 秒内返回200 disk cache (强缓存) | 5秒后资源变化返回200,不然304 |
| cache-control | max-age=3 | max-age=20 | max-age=5 | 20秒后返回 后端的 的权限大于 nginx |
| cache-control | max-age=3 | | max-age=5 | 5秒后资源变化返回200,不然304.结论是前端完全max-age不等于0的时候 没用 |
| cache-control | no-store | | max-age=5 | 5秒后资源变化返回200,不然304.结论是前端的no-store完全 没用 |
| cache-control | no-store | | no-store | 一直返回200 |
前后端nginx的的优先级
- 前端 meta 头设置 cache-control 不生效
- 前端只有 max-age=0 和 no-cache 生效
- 后端 no-cache不生效
说明
-
假如 后端一开始返回的是 cache-control 然后后面反悔了,cache-control 设置了 no-cache那么这个时候。前端仍然不会刷新。只有前端更改了请求才会刷新
-
base64 无论是从哪里得到的,基本都会存入 memory 内存里面
-
如果没有走proxy代理,那么 只能够监听静态资源,返回数据没办法做缓存和监听
-
如果是走了proxy 代理,那么nginx 中可以设置cache-control。这个时候有几种情况:
- 情况一 | 单一header:nginx 设置cache-control max-age,后端返回cache-control不设置 cache-control 请求的时候第二次能够拿到缓存数据
- 情况二 | 两个header | 后端和nginx同时设置header :这个时候我们可以发现 在header 设置 的 cache-control单一的时候,能够正常返回。那么我们现在来测试一下,nginx 和 后端同时设置cache-control。一般来说 header 是覆盖的 情况,但是 cache-control 是一个意外。他会迁就 去 服务器拿资源的选项例如 cache 设置 max-age=3 max-age=100000 .那么他这时候就是 max-age=3 。如果 no-cache 和 max = 100000 那么就是 no-cache的选项
- Cache-Control: no-cache 和 Cache-Control: max-age=0 是有区别的, Cache-Control: max-age=0 可能会直接走缓存,no-cache 表示 会向后端 发一条请求请求后端有没有改变。如果在 max-age 后面加上 must-revalidate 那么就和 no cache 一样了
-
情况三 | 三个header | 后端 nginx都设置了 header的 Cache-Control,然后前端 的 Cache-Control 也有.这种情况response和request的缓存都不太一样
- 3.1 前端 的 Cache-Control 设置成no-cache 那么 即使后端和 nginx设置了nginx 持久化也没有用,不可能304.现在看来no-cache 是用 前端 控制的 ,所以这部分的确可以
- 3.2 前端 的 Cache-Control max-age设置成0,12,表示这一次会这样。后端和nginx设置值的话,表示下一次会这样 会304。