小达不刘
0%

  1. 老生常谈的XSS
  2. 警惕iframe带来的风险
  3. 别被点击劫持了
  4. 错误的内容推断
  5. 防火防盗防猪队友:不安全的第三方依赖包
  6. 用了HTTPS也可能掉坑里
  7. 本地存储数据泄露
  8. 缺失静态资源完整性校验

XSS 跨站脚本攻击

是什么

XSS是跨站脚本攻击(Cross-Site Scripting)的简称,攻击者可以利用XSS漏洞来窃取包括用户身份信息在内的各种敏感信息、修改Web页面以欺骗用户,甚至控制受害者浏览器,或者和其他漏洞结合起来形成蠕虫攻击,等等。

如何防御

防御XSS最佳的做法就是对数据进行严格的输出编码,使得攻击者提供的数据不再被浏览器认为是脚本而被误执行。例如<script>在进行HTML编码后变成了&lt;script&gt;,而这段数据就会被浏览器认为只是一段普通的字符串,而不会被当做脚本执行了。

阅读全文 »

Vue3的新特性,如下:

  • 速度更快
  • 体积减少
  • 更易维护
  • 更接近原生
  • 更易使用

速度更快

vue3相比vue2

  1. 重写了虚拟Dom实现

  2. 编译模板的优化

  3. 更高效的组件初始化

  4. undate性能提高1.3~2倍

  5. SSR速度提高了2~3倍

体积更小

通过webpack的tree-shaking功能,可以将无用模块“剪辑”,仅打包需要的
能够tree-shaking,有两大好处:

  1. 对开发人员,能够对vue实现更多其他的功能,而不必担忧整体体积过大
  2. 对使用者,打包出来的包体积变小了
    vue可以开发出更多其他的功能,而不必担忧vue打包出来的整体体积过多

更易维护

阅读全文 »

小程序中经常会使用加解密提高安全性,此文采用对称加密,使用CryptoJS库,ECB模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

import { CryptoJS } from './CryptoJS'

/**
* 加密算法
* @param params 要加密的明文
* @param cryptoKey 秘钥
* @returns string
*/
export const encrypt = (params, cryptoKey) => {
const key = CryptoJS.enc.Utf8.parse(cryptoKey)
// 设置固定 iv 和 key 保证同样输入同样输出,可取消保证生成唯一性
const result = CryptoJS.TripleDES.encrypt(JSON.stringify(params), key, {
mode: CryptoJS.mode.ECB, // 模式
padding: CryptoJS.pad.Pkcs7, // 填充方式
})
return result.toString()
}

/**
* 解密算法
* @param result 要解密的密文
* @param cryptoKey 秘钥
* @returns Object
*/
export const decrypt = (result, cryptoKey) => {
const key = CryptoJS.enc.Utf8.parse(cryptoKey)
const decrypted = CryptoJS.TripleDES.decrypt(result, key, {
mode: CryptoJS.mode.ECB, // 模式
padding: CryptoJS.pad.Pkcs7, // 填充方式
}).toString(CryptoJS.enc.Utf8)

try {
return JSON.parse(decrypted)
} catch (e) {
return decrypted
}
}

阅读全文 »

背景:
setInterval和setTimeout实现的定时器在鸿蒙系统上会出现掉帧卡顿现象,比如倒计时中,10,9间隔长,8,7间隔又很短。

解决办法:用requestAnimationFrame实现定时功能。

高刷屏对setTimeout的影响

在低端机中,用setTimeout实现的动画可能会出现丢帧卡顿现象主要原因有以下两点:

  1. setTimeout回调执行时间不确定。因为setTimeout的回调会放在异步队列中,当主线程的任务执行完成后,才会检查异步队列中是否有要执行的任务,所以setTimeout执行的时间会比设定时间稍晚一些。
  2. 刷新频率受屏幕分辨率和屏幕尺寸的影响,因此不同设备的屏幕刷新频率可能会不同,而 setTimeout只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间相同。
    以上两种情况会是setTimeout的执行步调和屏幕刷新时间步调不一致,从而引起丢帧卡顿现象。

而在高刷屏下,因为屏幕刷新率更高,setTimeout执行的结果会很快被渲染在屏幕上,感觉会更丝滑,所以丢帧卡顿现象会削弱。

高刷屏对requestAnimationFrame的影响

requestAnimationFrame在屏幕刷新的时候执行,所以和屏幕刷新步调一致,用它实现的动画就会更丝滑,不会卡顿。

但感觉会耗性能一些,因为一分钟屏幕刷新多少次函数就执行多少次。

阅读全文 »

高效能人士的七个习惯

七个习惯

  1. 积极主动
  2. 以终为始
  3. 要事第一
  4. 双赢思维
  5. 知彼解己
  6. 统合综效
  7. 不断更新

摘录

  1. 潜在的、持久的、不断上升的成功才是值得称颂的。
阅读全文 »

一、类型转换

(1)原始值 -> 对象

1 原始值转字符串

String()

2 原始值转数字

方法一:
Number()
方法二:
算数函数或表达式:

变成……
undefined NaN
null 0
true和false 1 和 0
string 去掉首尾空格后的纯数字字符串中含有的数字。如果剩余字符串为空,则转换结果为 0。否则,将会从剩余字符串中“读取”数字。当类型转换出现 error 时返回 NaN。

注意:
如果通过 Number 转换函数传入一个字符串,它会试图将其转换成一个整数或浮点数,而且会忽略所有前导的 0,如果有一个字符不是数字,结果都会返回 NaN,鉴于这种严格的判断,我们一般还会使用更加灵活的 parseInt 和 parseFloat 进行转换。

parseInt 只解析整数,parseFloat 则可以解析整数和浮点数,如果字符串前缀是 “0x” 或者”0X”,parseInt 将其解释为十六进制数,parseInt 和 parseFloat 都会跳过任意数量的前导空格,尽可能解析更多数值字符,并忽略后面的内容。如果第一个非空格字符是非法的数字直接量,将最终返回 NaN:

阅读全文 »

数据类型

基本类型:

  1. Boolean;
  2. Null;
  3. Undefined;
  4. Number;
  5. String;

引用类型 :
6. Objects: Array, function, Date

新增:
7. BigInt: 谷歌67版本出现的数据类型, 是指安全存储、操作大整数,(但是很多人不把这个做为一个类型);
8. Symbol:ES6新增, 这种类型的对象永不相等,即始创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记;

类型判断

  • typeof
  • instanceof
  • Object.prototype.toString
  • isXXX,比如 isArray

typeof:返回一个字符串

阅读全文 »

Upstart是什么?

Upstart是领先的人工智能(AI)贷款平台,旨在改善人们负担得起的信贷的使用率,同时降低银行合作伙伴的贷款风险和成本。 通过利用Upstart的AI平台,支持Upstart的银行可以提供更高的批准率,并降低损失率(不良貸款率),同时提供客户所需的卓越的数字优先贷款体验。

运作模式

Upstart与银行间的服务模式是由Upstart负责带入客户,以AI审核贷款跟决定利率,实际由银行合作伙伴完成实际贷款的流程,而Upstart负责抽成[1]。它的一些产品包括个人贷款、婚礼贷款、信用卡合併和汽车贷款。Upstart贷款年利率在 8.27% 到 35.99% 之间,具体取决于产品。合作银行通过这样的促销方式将可带来更多的用户流量与稳定使用率,在未来也能够针用户们提供贷款以外的产品与客制化服务,提升客户的黏度[2]。

模型

美國傳統的信貸模型是利用FICO[3]來計算信用分數,但此方法量化風險的能力有限,目前,该公司的人工智能模型包含了1000多个变量来提供决策。公司的人工智能平台已经通过1050万多个还款事件进行自我学习,实时自我优化模型。Upstart 的演算法能够根据非传统指标评估借款人。如除了他们的工作经历之外,它还考虑了借款人的教育和他们上学的地方,而不仅是收入和资产。公司声称其决策过程可以将违约率降低 75%。事实上,在相同的整体贷款损失率下,Upstart批出的贷款数目比美国大型银行多173% 。

展望

另一方面,Upstart 当前的商业模式以及产品也都还未发展完善 ,以用户面来看,目前散户投资人还无法利用 Upstart 平台进行投资;以产品面来看,Upstart 目前的贷款方案种类相较其他成熟的 P2P 借贷市场来的少;以商业范畴面(scope)来看,Upstart 目前仍仅提供贷款相关的产品及服务,其他如理财投资等商业模式亦尚未被开发 。
因此我们认为,若是 Upstart 能够在精准判断申贷人的信用风险并比其他业者有更低的违约率、外加产品的广度也能够持续发展,公司未来前景是值得期待[2]。

参考:
[1].美國AI貸款平台UPSTART介紹:https://www.find.org.tw/index/wind/browse/39a09ecd2ac75c0b646cb60e74fcb49b/
[2].https://dreamloan.com.tw/articles/13-Upstart-%E4%BF%A1%E7%94%A8%E8%A9%95%E5%88%86-%E5%AD%B8%E7%94%9F%E8%B2%B8%E6%AC%BE-%E4%BA%BA%E5%B7%A5%E6%99%BA%E6%85%A7
[3].FICO模型: https://usdailyrewards.com/fico-score/

阅读全文 »

useState是什么?

useState()是改变状态的开关,将状态添加到函数组件需要4个步骤:启用状态、初始化、读取和更新。

使用方法

场景: 有4个tab键需要切换,当切换不同tab时,要在指定区域内渲染指定的自定义组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

import React, { useState } from 'react'; // 启用状态
import styles from './index.module.less';
import ComponentZero from './ComponentZero';
import ComponentOne from './ComponentOne';
import ComponentTwo from './ComponentTwo';
import ComponentThree from './ComponentThree';

fuction ControlTabActive() {
// 初始化状态为 1
const [selectStatus, setSelectStatus] = useState(1);
const tabsList = [
{ label: 'Tab1'},
{ label: 'Tab2'},
{ label: 'Tab3'},
{ label: 'Tab4'},
];
return (
<div className="app">
<div className="tab">
{
tabsList.map((item, index) =>
<div key={index}
className={`${styles.navitem} ${selectStatus === index ? styles.active : ''}`}
// 更新状态
onClick={() => setSelectStatus(index)}>
{item.label}
</div>)
}
</div>
{/*读取状态*/}
<div className="main">
{selectStatus === 0 ? <ComponentZero /> : ''}
{selectStatus === 1 ? <ComponentOne /> : ''}
{selectStatus === 2 ? <ComponentTwo /> : ''}
{selectStatus === 3 ? <ComponentThree /> : ''}
</div>
</div>
)
}

多种状态、状态的延迟初始化、seState() 中的坑等点击查看: https://www.jianshu.com/p/700777ea9db0

阅读全文 »

什么是require.context

一个webpack的api,通过执行require.context函数获取一个特定的上下文,主要用来实现自动化导入模块,在前端工程中,如果遇到从一个文件夹引入很多模块的情况,可以使用这个api,它会遍历文件夹中的指定文件,然后自动导入,使得不需要每次显式的调用import导入模块。

require.context使用场景

1
2
3
4
5
6
import home from '../page/home';
import demo from '../page/demo';
import lcdp from '../page/lcdp';
import table from '../page/table';
import form from '../page/form';
import detail from '../page/detail';

可以使用require.context:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 获取全部modules目录
const modulesFiles = require.context('../pages', true, /^[.](\/[^/]*)\/index\.js$/);

// 组织modules为数组
const appModules = modulesFiles.keys().reduce((modules, modulePath) => {
const value = modulesFiles(modulePath);
const moduleName = modulePath.match(/\.\/(\S*)\//)[1];
modules.push({
moduleName,
module: value.default,
});
return modules;
}, []);

export { appModules };

require.context使用方法

require.context函数接受三个参数:

  1. directory {String} -读取文件的路径
  2. useSubdirectories {Boolean} -是否遍历文件的子目录
  3. regExp {RegExp} -匹配文件的正则
阅读全文 »