一、前端登录案例和实现
1.Cookie + Session
用户首次登录时,输入账号和密码登录,服务端验证账号和密码无误后,会创建sessionid,然后将该sessionid保存到session中,服务器端响应这个http请求,通过set-cookie,将sessionid写入到cookie中,后续访问请求都会携带的cookie中的id,服务端比对cookie中的sessionid和session中的id是否一致进行验证。
由于 SessionId 存放在 Cookie 中,所以无法避免 CSRF 攻击
2.Token 登录
用户输入账号密码,并点击登录,服务器端验证账号密码无误,创建 Token,服务器端将 Token 返回给客户端,由客户端自由保存,客户端在请求是header中携带token,服务器端验证 Token ,有效则身份验证成功。
Token 生成方式是常使用 JWT
JWT 算法主要分为 3 个部分:header(头信息),playload(消息体),signature(签名)
header 部分指定了该 JWT 使用的签名算法:header = '{"alg":"HS256","typ":"JWT"}' // `HS256` 表示使用了 HMAC-SHA256 来生成签名。
playload 部分表明了 JWT 的意图:payload = '{"loggedInAs":"admin","iat":1422779638}'
signature 部分为 JWT 的签名,主要为了让 JWT 不能被随意篡改,签名的方法分为两个步骤:
- 输入
base64url
编码的 header 部分、base64url
编码的 playload 部分,输出 unsignedToken。(`${base64Header}.${base64Payload}`) - 输入服务器端私钥、unsignedToken,输出 signature 签名(HMAC(key, unsignedToken))
3.单点登录sso
单点登录指的是在公司内部搭建一个公共的认证中心,公司下的所有产品的登录都可以在认证中心里完成,一个产品在认证中心登录后,再去访问另一个产品,可以不用再次登录,即可获取登录状态。
1.以Cookie作为凭证媒介
是使用cookie作为媒介,存放用户凭证。 用户登录父应用之后,应用返回一个加密的cookie,当用户访问子应用的时候,携带上这个cookie,授权应用解密cookie并进行校验,校验通过则登录当前用户
2.认证中心
-
用户访问网站
a.com
下的 pageA 页面。 -
由于没有登录,则会重定向到认证中心,并带上回调地址
www.sso.com?return_uri=a.com/pageA
,以便登录后直接进入对应页面。 -
用户在认证中心输入账号密码,提交登录。
-
认证中心验证账号密码有效,然后重定向
a.com?ticket=123
带上授权码 ticket,并将认证中心sso.com
的登录态写入 Cookie。 -
在
a.com
服务器中,拿着 ticket 向认证中心确认,授权码 ticket 真实有效。 -
验证成功后,服务器将登录信息写入 Cookie(此时客户端有 2 个 Cookie 分别存有
a.com
和sso.com
的登录态)。 -
认证中心登录完成之后,继续访问
a.com
下的其他页面,这个时候,由于a.com
存在已登录的 Cookie 信息,所以服务器端直接认证成功 -
如果认证中心登录完成之后,访问
b.com
下的页面,这个时候,由于认证中心存在之前登录过的 Cookie,所以也不用再次输入账号密码,直接返回第 4 步,下发 ticket 给b.com
即可。
sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。间接授权通过令牌实现,sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。
退出登录
-
清空
c.com
中的登录态 Cookie。 -
请求认证中心
sso.com
中的退出 api。 -
认证中心遍历下发过 ticket 的所有产品,并调用对应的退出 api,完成退出
3.页面重定向
是通过父应用和子应用来回重定向中进行通信,实现信息的安全传递。 父应用提供一个GET方式的登录接口,用户通过子应用重定向连接的方式访问这个接口,如果用户还没有登录,则返回一个的登录页面,用户输入账号密码进行登录。如果用户已经登录了,则生成加密的Token,并且重定向到子应用提供的验证Token的接口,通过解密和校验之后,子应用登录当前用户
4.OAuth三方登录
-
首先,
a.com
的运营者需要在微信开放平台注册账号,并向微信申请使用微信登录功能。 -
申请成功后,得到申请的 appid、appsecret。
-
用户在
a.com
上选择使用微信登录。 -
这时会跳转微信的 OAuth 授权登录,并带上
a.com
的回调地址。 -
用户输入微信账号和密码,登录成功后,需要选择具体的授权范围,如:授权用户的头像、昵称等。
-
授权之后,微信会根据拉起
a.com?code=123
,这时带上了一个临时票据 code。 -
获取 code 之后,
a.com
会拿着 code 、appid、appsecret,向微信服务器申请 token,验证成功后,微信会下发一个 token。 -
有了 token 之后,
a.com
就可以凭借 token 拿到对应的微信用户头像,用户昵称等信息了。 -
a.com
提示用户登录成功,并将登录状态写入 Cooke,以作为后续访问的凭证。
二、项目中做哪些性能优化
1、Vue项目中优化
(1)路由懒加载
在项目打包构建完,js包会变的很大,就会影响到页面加载,这时候可以结合vue的异步组件和Webpack 或keep-alive的代码分割功能
- vue的异步组件和webpack代码分割code Splitting
在vue以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。当使用局部注册的时候,可以直接提供一个返回 Promise
的函数,在 Webpack 2 中,我们可以使用动态import语法来定义代码分块点(如果您使用的是 Babel,你将需要添加 syntax-dynamic-import
插件)。结合这两者,这就是如何定义一个能够被 Webpack 自动代码分割的异步组件
components: {
'my-component': () => import('./my-async-component')
}
Vue.component(
'async-webpack-example',
// 这个动态导入会返回一个 `Promise` 对象。
() => import('./my-async-component')
)
把组件按组分块
有时候我们想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用 命名 chunk,一个特殊的注释语法来提供 chunk name 、
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
- keep-alive
有三个属性:
include
- 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude
- 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max
- 数字。最多可以缓存多少组件实例。
<keep-alive>
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们
当组件在 <keep-alive>
内被切换,它的 activated
和 deactivated
这两个生命周期钩子函数将会被对应执行
注:<transition>
元素作为单个元素/组件的过渡效果。<transition>
只会把过渡效果应用到其包裹的内容上,而不会额外渲染 DOM 元素,也不会出现在可被检查的组件层级中
(2)http连接优化
- 减少HTTP请求
-
合并CSS、js、图片。将css、js、图片合并,可以有效减少http请求数;
-
合理规划API,将可合并的接口请求合并。浏览器对并发的http请求数量有限制,即使API响应很快,在多个接口并发请求时,仍会在浏览器中造成不同程度的卡顿(如ie中部分请求挂起,内存占用变大等)
2.合理使用缓存
合理设置HTTP缓存。从图1 浏览器请求处理流程图中可以看出,恰当的缓存设置可以大大减少HTTP请求,节省带宽。如很少变化的资源(html、css、js、图片等)通过 HTTP Header中的cache-control和Expires可设定浏览器缓存,变化不频繁又可能变的资源使用Last-Modifed来做请求验证
3.使用字体图标
建议使用字体图标代替纯色或渐变色的图标,如使用icomoon。在准备好svg文件后,可通过https://icomoon.io/在线制作字体图标,需要维护时可导入json文件重新编辑。
使用字体图标的优点:
-
轻量:一个图标字体比一系列的图像(特别是在Retina屏中使用双倍图像)要小。一旦图标字体加载了,图标就会马上渲染出来,不需要下载一个图像。可以减少HTTP请求,还可以配合HTML5离线存储做性能优化;
-
灵活性:图标字体可以用过font-size属性设置其任何大小,还可以加各种文字效果,包括颜色、Hover状态、透明度、阴影和翻转等效果。可以在任何背景下显示。使用位图的话,必须得为每个不同大小和不同效果的图像输出一个不同文件。
-
兼容性:网页字体支持所有现代浏览器,包括IE低版本。
4.图片懒加载
在实际的项目开发中,我们通常会遇见这样的场景:一个页面有很多图片,而首屏出现的图片大概就一两张,那么我们还要一次性把所有图片都加载出来吗,这样是不可能的,这也就是们通常所说的首屏加载,技术上现实其中要用的技术就是图片懒加载--到可视区域再加载
将页面里所有img属性src属性用data-xx代替,当页面滚动直至此图片出现在可视区域时,用js取到该图片的data-xx的值赋给src
JQ:jqueryLazyload
echo.js:Echo.init
(3)组件优化
-
按模块划分路由。按照业务模块划分路由及子路由,保证模块间的隔离;如果把所有的组件的布局写在一个组件中,当数据变更时,由于组件代码比较庞大,vue 的数据驱动视图更新会比较慢,造成渲染过慢,也会造成比较差的体验效果。所以要把组件细分
-
模块内按布局或功能划分组件。单个模块功能较多或逻辑较复杂时,按照布局划分为左右或上下及其组合模式划分组件,以子组件的方式放在模块中,方便打包优化、复用、功能拓展及维护;
-
能复用的组件尽量复用。布局、功能模块等均可复用,如:tab中的筛选条件、详情弹窗、表单等
具体优化方案:
- v-if v-show,条件渲染
- 动态组件component中的is属性
- v-once只渲染元素和组件一次,随后的渲染,使用了此指令的元素/组件及其所有的子节点,都会当作静态内容并跳过,这可以用于优化更新性能。
- 不要在模板里面写过多的表达式与判断,这种表达式虽说可以识别,代码阅读性很差,适当的写到 methods 和 computed 里面封装成一个方法,这样的好处是方便我们在多处判断相同的表达式,其他权限相同的元素再判断展示的时候调用同一个方法即可
- 循环调用子组件时添加 key,key 可以唯一标识一个循环个体
- 组件引入优化:
单独建立一个js文件,用来完成组件引入
使用:require.context
require.context函数接受三个参数
directory {String} -读取文件的路径
useSubdirectories {Boolean} -是否遍历文件的子目录
regExp {RegExp} -匹配文件的正则
function strFirstCharUpper(str) {
// 组件名首字母大写
return str.charAt(0).toUpperCase() + str.slice(1)
}
console.log(requireComponent.keys()) // ['./child1.vue','./child2.vue']
requireComponent.keys().forEach(fileName => {
console.log(fileName)
// 拿到对应的组件配置
const config = requireComponent(fileName)
const componentName = strFirstCharUpper(
fileName.replace(/^\.\//,'').replace(/\.\w+$/,'')
)
// config.default 组件文件以对象方式返回
Vue.component(componentName, config.default || config)
});
(4)打包优化
打包 vender 时不打包 vue、vuex、vue-router、axios 等,换用国内的bootcdn直接引入到根目录的 index.html 中
<script src="//cdn.bootcss.com/vue/2.2.5/vue.min.js"></script>
<script src="//cdn.bootcss.com/vue-router/2.3.0/vue-router.min.js"></script>
<script src="//cdn.bootcss.com/vuex/2.2.1/vuex.min.js"></script>
<script src="//cdn.bootcss.com/axios/0.15.3/axios.min.js"></script>
在 webpack 里有个 externals,可以忽略不需要打包的库
externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex': 'Vuex',
'axios': 'axios'
}
(5)代码优化
1.第三方引入优化
-
去除不必要的引入,如jq;
-
按需引入echarts包,ui组件;
2.全局style尽量抽象,提高复用率,减小css文件大小,节省带宽
3.提取共用的方法,放在util.js中,例如表单校验的封装
4.合理使用vuex,redux
(6)webpack优化
- 对于 Webpack4,打包项目使用 production 模式,这样会自动开启代码压缩
- 使用 ES6 模块来开启 tree shaking,这个技术可以移除没有使用的代码
- 优化图片,对于小图可以使用 base64 的方式写入文件中
- 给打包出来的文件名添加哈希,实现浏览器缓存文件
- 利用cdn加速。在构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用webpack对于output参数和各loader的publicPath参数来修改资源路径
- 删除死代码(Tree Shaking)。将代码中永远不会走到的片段删除掉。可以通过在启动webpack时追加参数--optimize-minimize来实现
-
optimization: {minimize: false}关闭单个构建文件的大小限制
(7)vue项目中实现按需加载
Element出品的babel-plugin-component和AntDesign出品的babel-plugin-import 安装以上插件后,在.babelrc配置中或babel-loader的参数中进行设置,即可实现组件按需加载了。
module.exports= {
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
(8)项目构建中和完成后
-
开启eslint验证,看到错误和警告信息及时解决;
-
打开浏览器调试窗口,查看Network中从发起网页页面请求Request后分析HTTP请求后得到的各个请求资源信息(包括状态、资源类型、大小、所用时间等),可以根据这个进行网络性能优化。如查看哪些http请求返回资源非常大或耗用时间较长,可针对处理;
-
打开浏览器调试窗口,在Timeline中记录并分析在网站的生命周期内所发生的各类事件,以此可以提高网页的运行时间的性能;
-
代码编写过程中不断思考是否可优化模块或做共性组件提取,及时代码审核,提高代码质量
2、预加载
在开发中,可能会遇到这样的情况。有些资源不需要马上用到,但是希望尽早获取,这时候就可以使用预加载。
预加载其实是声明式的 fetch
,强制浏览器请求资源,并且不会阻塞 onload
事件,可以使用以下代码开启预加载
<link rel="preload" href="http://example.com" />
预加载可以一定程度上降低首屏的加载时间,因为可以将一些不影响首屏但重要的文件延后加载,唯一缺点就是兼容性不好。
3.预渲染
可以通过预渲染将下载的文件预先在后台渲染,可以使用以下代码开启预渲染
<link rel="prerender" href="http://example.com" />
预渲染虽然可以提高页面的加载速度,但是要确保该页面百分百会被用户在之后打开,否则就白白浪费资源去渲染
三、webpack面试题
1.有哪些常见的Loader?他们是解决什么问题的?Loader在module.rules中配置(test,loader,options{limit,name})
- ile-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
- url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去
- source-map-loader:加载额外的 Source Map 文件,以方便断点调试
- image-loader:加载并且压缩图片文件
- babel-loader:把 ES6 转换成 ES5
- css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
- style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。
- eslint-loader:通过 ESLint 检查 JavaScript 代码
2.有哪些常见的Plugin?他们是解决什么问题的?Plugin在plugins中单独配置
- define-plugin:定义环境变量
- commons-chunk-plugin:提取公共代码
- uglifyjs-webpack-plugin:通过UglifyES压缩ES6代码
- UglifyJsPlugin:来压缩JS文件
-
ExtractTextPlugin:该插件的主要是为了抽离css样式,防止将样式打包在js中引起页面样式加载错乱的现象
3.webpack的构建流程是什么?
- 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;
- 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;
- 确定入口:根据配置中的 entry 找出所有的入口文件;
- 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;
- 完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;
- 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
- 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
四、Chrome开发者工具详解
1.Chrome开发者工具面板包含了:Elements、Console、Sources、Network、Timeline、Profiles、Application、Security、Audits。这 些功能面板。
这些按钮的功能如下:
-
Elements:查找网页源码HTML中的任意元素,手动修改任一元素的属性和样式且能实时在浏览器里面得到反馈。
-
Console:记录开发者开发过程中的日志信息,且可以作为与JS进行交互的命令行Shell。
-
Sources:断点调试JS
-
Network:从发起网页页面请求,Request后分析HTTP请求后得到的请求资源信息包括(状态、类型、大小、用时等),可以根据这些信息,进行网络性能优化。
-
Performance:记录和分析页面在运行时的所有活动,比如记录执行JS CPU执行的时间细节,显示JS对象和相关DOM节点的内存消息,记录内存分配细节等。
利用Performance面板,可以追踪到网页程序的内存泄漏问题,进一步提升程序的JavaScript执行性能
controls:开始记录、停止记录和配置记录期间捕获的信息
overview:页面性能优化的高级汇总
火焰图:CPU堆叠追踪的可视化
统计汇总:以图表形式汇总数据
-
Application:记录网站加载的所有资源信息,包括存储数据,缓存数据,字体,图片,脚本,样式等(cookie,localStorage,sessionStorage,indexedDB,WebSQL)。
cookie属性:
value:如果用于保存用户登录态,应该将该值加密,不能使用明文的用户标识
http-only:不能通过 JS 访问 Cookie,减少 XSS 攻击
secure:只能在协议为 HTTPS 的请求中携带
same-site:规定浏览器不能在跨域请求中携带 Cookie,减少 CSRF 攻击
-
Memory:可以查看更多内存信息快照。
-
Security:判断当前网页是否安全。
-
Audits:对当前网页进行网络利用情况,网页性能方面的诊断,并给出优化建议。例如列出所有没有用到的CSS文件等。
2.GC 算法
GC 算法采用了分代式垃圾回收机制。因此,V8 将内存(堆)分为新生代和老生代两部分:
新生代算法
新生代中的对象一般存活时间较短,在新生代空间中,内存空间分为两部分,分别为 From 空间和 To 空间。在这两个空间中,必定有一个空间是使用的,另一个空间是空闲的。新分配的对象会被放入 From 空间中,当 From 空间被占满时,新生代 GC 就会启动了。算法会检查 From 空间中存活的对象并复制到 To 空间中,如果有失活的对象就会销毁。当复制完成后将 From 空间和 To 空间互换,这样 GC 就结束了。
老生代算法
老生代中的对象一般存活时间较长且数量也多,使用了两个算法,分别是标记清除算法和标记压缩算法。
- 新生代中的对象是否已经经历过一次 Scavenge 算法,如果经历过的话,会将对象从新生代空间移到老生代空间中。
- To 空间的对象占比大小超过 25 %。在这种情况下,为了不影响到内存分配,会将对象从新生代空间移到老生代空间中。
五、组件封装及发布
1.ui组件库构建相关配置
按需引入构建配置:
entry:多个入口文件,json类型存放
output:输出文件
path: path.resolve(process.cwd(), './lib'), 存放位置
filename: '[name]/index.js', 文件名
libraryTarget: 'commonjs2', 采用的导出规范
单组件暴露
// 导入组件,组件必须声明 name
import Switch from './src/switch.vue'
// 为组件提供 install 安装方法,供按需引入
Switch.install = function (Vue) {
Vue.component(Switch.name, Switch)
}
// 默认导出组件
export default Switch
全局组件暴露
const install = function (Vue) {
// 遍历注册全局组件
components.forEach(component => {
Vue.component(component.name, component)
})
}
// 判断是否是直接引入文件
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default {
// 导出的对象必须具有 install,才能被 Vue.use() 方法安装
install,
// 以下是具体的组件列表
...components
}
全局注入
Vue.use()
2.npm发布
1.登录npm
npm login
2.npm 发布
npm publish --access=public
3.npm 更新
npm version patch
npm publish
4.npm 删除
npm unpublish @wthreesix/testtemplate@1.0.1
5.强制删除npm包
npm unpublish @wthreesix/testtemplate --force
3.打架私有镜像库
1.安装Verdaccio
npm install -g verdaccio
2.查看verdaccio有哪些命令
verdaccio -h
3.启动这个服务
verdaccio
4.verdaccio的配置文件
/.config/verdaccio/config.yaml
(1)端口和地址:listen
(2)上传的资源包文件配置位置 : storage
(3)插件:plugins
(4)标题:web: title:
(5)packages:在私有仓库没有找到时去哪代理这个包
将packages做配置只发布到私有仓库:设置为:‘@fosafer/*’
(6)权限配置auth
(7)uplinks,将官网源当成第三方源
5.设置npm的源
(1)安装nrm
npm i -g nrm
(2)查看已有的源
nrm ls
(3)删除已有的源
nrm del 源
(4)添加源
nrm add ynpm http://10.10.11.40:4873/
(5)使用新添加的镜像
nrm use ynpm
(6)添加用户
npm addUser
输入用户名,密码,邮箱
(7)发布包
进去到要发布的包根目录下
npm publish
6.进程守卫
(1)安装pm2
npm i -g pm2
(2)pm2 list
(3)pm2 start verdaccio
六、网络安全
1.XSS跨域脚本攻击
- 如何攻击
不需要登录,是一种网站应用程序的安全漏洞攻击,它允许恶意使用者将程式码注入到网页上,其他使用者在观看网页时就会受到影响。这类攻击通过修改 HTML 节点或者执行 JS 代码来攻击网站。
- 如何防御
(1)建立可信任的字符和 HTML 标签白名单,对于不在白名单之列的字符或者标签进行过滤或编码。可使用了 js-xss
来实现。可以看到在输出中保留了 h1
标签且过滤了 script
标签
(2)编码:对敏感字符进行转义,才能进行下一步操作,<>、$、'等字符,alert、$
(3) 过滤:onclick等事件、style、script节点、iframe节点
(4)http-only:不能通过 JS 访问 Cookie,减少 XSS 攻击
(5)CSP内容安全策略,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件,这些攻击都是主要的手段。CSP 本质上也是建立白名单,规定了浏览器只能够执行特定来源的代码。
通常可以通过 HTTP Header 中的 Content-Security-Policy
来开启 CSP
-
只允许加载本站资源
Content-Security-Policy: default-src ‘self’
-
只允许加载 HTTPS 协议图片
Content-Security-Policy: img-src https://*
-
允许加载任何来源框架
Content-Security-Policy: child-src 'none'
- 案例场景
留言板的XSS攻击,窃取用户账号密码,带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等
2.CSRF跨站请求伪造
- 如何攻击
需要用户先登录网站A,获取 cookie,是利用网站本身的漏洞,去请求网站A的api,假设网站中有一个通过 Get 请求提交用户评论的接口,那么攻击者就可以在钓鱼网站中加入一个图片,图片的地址就是评论接口。
- 如果防御
(1)Get 请求不对数据进行修改
(2)不让第三方网站访问到用户 Cookie
(3)阻止第三方网站请求接口
(4)请求时附带验证信息,比如验证码或者 token
(5)双重Cookie验证 以及配合 Cookie 设置 SameSite
属性。该属性设置 Cookie 不随着跨域请求发送,该属性可以很大程度减少 CSRF 的攻击,但是该属性目前并不是所有浏览器都兼容
(6)对于需要防范 CSRF 的请求,使用同源检测(Origin 和 Referer 验证)我们可以通过验证 Referer 来判断该请求是否为第三方网站发起的(Referer标识当前请求的来源页面,浏览器访问时除了自动带上Cookie还会自动带上Referer,所以服务端可以检测Referer头是否本网站页面来决定是否响应请求。Referer是浏览器自动带上的,基于认为浏览器没有相关漏洞的前提下,我们可以认为攻击者是没法伪造Referer头的,也就是检测Referer头的方法是可靠的。但该方式有时会不受认可,一是因为浏览器是可以设置禁止发送Referer头的,如果使用该方式那么禁止Referer头的浏览将无法正常使用,这可能会降低用户使用体验。二是因为由于移动端的崛起当下流行前后端分离app和web共用一套后端代码,但app是不会自动带Referer头的,如果使用该方式app端不好处理。)
(7)服务器下发一个随机 Token(算法不能复杂),每次发起请求时将 Token 携带上,服务器验证 Token 是否有效。
- 案例场景
银行卡转账,微博发帖删帖等
3.加密解密
1.几种对称性加密算法:AES,DES,3DES
DES是一种分组数据加密技术(先将数据分成固定长度的小数据块,之后进行加密),速度较快,适用于大量数据加密,而3DES是一种基于DES的加密算法,使用3个不同密匙对同一个分组数据块进行3次加密,如此以使得密文强度更高。
相较于DES和3DES算法而言,AES算法有着更高的速度和资源使用效率,安全级别也较之更高了,被称为下一代加密标准。
2.几种非对称性加密算法:RSA,DSA,ECC
RSA和DSA的安全性及其它各方面性能都差不多,而ECC较之则有着很多的性能优越,包括处理速度,带宽要求,存储空间等等。
3.几种线性散列算法(签名算法):MD5,SHA1,HMAC
这几种算法只生成一串不可逆的密文,经常用其效验数据传输过程中是否经过修改,因为相同的生成算法对于同一明文只会生成唯一的密文,若相同算法生成的密文不同,则证明传输数据进行过了修改。通常在数据传说过程前,使用MD5和SHA1算法均需要发送和接收数据双方在数据传送之前就知道密匙生成算法,而HMAC与之不同的是需要生成一个密匙,发送方用此密匙对数据进行摘要处理(生成密文),接收方再利用此密匙对接收到的数据进行摘要处理,再判断生成的密文是否相同
5.前端使用md5加密解密
使用JS函数的escape()和unescape()
6.BASE64加密解密
使用JS函数的btoa()和atob()
七、vue2.0和vue3.0区别
1.重构响应式系统,使用Proxy替换Object.defineProperty,使用Proxy优势:
-
可直接监听数组类型的数据变化
-
监听的目标为对象本身,不需要像Object.defineProperty一样遍历每个属性,有一定的性能提升
-
可拦截apply、ownKeys、has等13种方法,而Object.defineProperty不行
-
直接实现对象属性的新增/删除
2.新增Composition API,更好的逻辑复用和代码组织
-
setup是compositionApi的入口
-
Vue的API设计迫使开发者使用watch,computed,methods选项组织代码,而不是实际的业务逻辑
-
Vue2.0缺少一种较为简洁的低成本的机制来完成逻辑复用,虽然可以minxis完成逻辑复用,但是当mixin变多的时候,会使得难以找到对应的data、computed或者method来源于哪个mixin,使得类型推断难以进行
-
Composition API的出现,主要是也是为了解决Option API带来的问题,可以让开发者根据业务逻辑组织自己的代码,让代码具备更好的可读性和可扩展性
-
实现代码的逻辑提取与复用
3.重构 Virtual DOM
-
模板编译时的优化,将一些静态节点编译成常量
-
slot优化,将slot编译为lazy函数,将slot的渲染的决定权交给子组件
-
模板中内联事件的提取并重用(原本每次渲染都重新生成内联函数)
-
.代码结构调整,更便于Tree shaking,使得体积更小
-
使用Typescript替换Flow
4.移除了 static 文件夹,新增 public 文件夹,并且 index.html 移动到 public 中
5.vue-cli3.0移除了配置文件目录,config 和 build 文件夹。从config/index.js 挪到了vue.config.js中
6.Vue2.x中new出的实例对象,所有的东西都在这个vue对象上,这样其实无论你用到还是没用到,都会跑一变。vue3.0中可以用ES module imports按需引入,如:keep-alive内置组件
八、vue和react框架理解
1.Vue 是一个构建数据驱动的渐进性框架,它的目标是通过 API 实现响应数据绑定和视图 更新。
2.Vue 的优缺点:数据驱动视图、组件化、强大且丰富的 API 提供一系列的 api 能满足业务开发中各类需求、采用虚拟dom、生态好,社区活跃。
3.语法上 Vue 并不限制你必须 es6+完全 js 形式编写页面,可以视图和 js 逻辑尽可能分离,react使用jsx。vue是把html,css,js组合到一起,用各自的处理方式,vue有单文件组件,可以把html、css、js写到一个文件中,html提供了模板引擎来处理。
4.react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以在react中,是单向数据流,vue的思想是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom
5.react的性能优化需要手动去做,而vue的性能优化是自动的,但是vue的响应式机制也有问题,就是当state特别多的时候,Watcher也会很多,会导致卡顿,所以大型应用(状态特别多的)一般用react,更加可控。
6.react是类式的写法,api很少,而vue是声明式的写法,通过传入各种options,api和参数都很多。所以react结合typescript更容易一起写,vue稍微复杂。vue结合vue-class-component也可以实现类式的写法,但是还是需要通过decorator来添加声明,并不纯粹。
7.react可以通过高阶组件(Higher Order Components--HOC)来扩展,而vue需要通过mixins来扩展
8.react做的事情很少,很多都交给社区去做,vue很多东西都是内置的,写起来确实方便一些