其他

478 阅读7分钟

其他:

淘系、华系、腾系等面试题:

github.com/CavsZhouyou…

安全:

  • XSS攻击(Cross-Site Scripting)即跨站脚本攻击:

是一种代码注入攻击。比如在一个网站能输入的地方输入一些恶意脚本,由于直接在用户的终端执行,恶意代码能够直接获取用户的信息,利用这些信息冒充用户向网站发起攻击者定义的请求。 攻击者向有 XSS 漏洞的网站中输入恶意的 HTML 代码,当其它用户浏览该网站时候,该段 HTML 代码会自动执行,从而达到攻击的目的,如盗取用户的 Cookie,破坏页面结构,重定向到其它网站等 。

防御:

利用正则检查输入内容进行过滤,对输入的内容进行转义,比如:

  1. & 替换 为: &
  2. < 替换为 &lt
  3. 替换为&gt ;

  4. ‘’ 替换为 &quot;
  5. ’ 替换为 &#x27;
  6. / 替换为 &#x2f;
  • CSRF攻击(Cross-site request forgery)即跨域请求伪造:

原理:

  • 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
  • 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
  • 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
  • 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
  • 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行

防御:

CSRF攻击之所以能够成功,是因为服务器误把攻击者发送的请求当成了用户自己的请求。那么我们可以要求所有的用户请求都携带一个CSRF攻击者无法获取到的Token。服务器通过校验请求是否携带正确的Token,来把正常的请求和攻击的请求区分开。跟验证码类似,只是用户无感知。 服务端给用户生成一个token,加密后传递给用户 用户在提交请求时,需要携带这个token 服务端验证token是否正确。

HTML5和CSS3常问:

www.cnblogs.com/huqinhan/p/…

MVVM中的双向绑定:

由视图(View)、视图模型(ViewModel)、模型(Model)三部分组成。vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。

1.当一个对象(或变量)的属性改变,那么调用这个属性的地方显示也应该改变,模型到视图(model => view)

2.当调用属性的这个地方改变了这个属性(通常是一个表单元素),那么这个对象(或变量)的属性也会改为最新的值 ,即视图到模型(view => model)

如下通过defineProperty实现双向绑定例子:

PS:加入了 用户输入中文的判断(用户输入中文时,频繁触发 keyup事件,但实际上输入并没有结束。)

语法: Object.defineProperty(obj, prop, descriptor)

obj: 需要被操作的目标对象
prop: 目标对象需要定义或修改的属性的名称
descriptor: 将被定义或修改的属性的描述符

var obj = new Object();

Object.defineProperty(obj, 'name', {
    configurable: false,
    writable: true,
    enumerable: true,
    value: '张三'
})

console.log(obj.name)  //张三

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>双向绑定</title>
</head>
<body>
  手写一个简单双向绑定<br/>
  <input type="text" id="model"><br/>
  <div id="modelText"></div>
</body>
<script>
  var model = document.querySelector("#model");
  var modelText = document.querySelector("#modelText");
  var defaultName = "defaultName";
  var userInfo = {}
  model.value = defaultName;
  Object.defineProperty(userInfo, "name", {
    get: function () {
      return defaultName;
    },
    set: function (value) {
      defaultName = value;
      model.value = value;
      console.log("-----value");
      console.log(value);
      modelText.textContent = value;
    }
  })

  userInfo.name = "new value";
  var isEnd = true;

  model.addEventListener("keyup", function () {
    if (isEnd) {
      userInfo.name = this.value;
    }
  }, false)
  //加入监听中文输入事件
  model.addEventListener("compositionstart", function () {
    console.log("开始输入中文");
    isEnd = false;
  })
  model.addEventListener("compositionend", function () {
    isEnd = true;
    console.log("结束输入中文");
  })
</script>
</html>

每当通过userInfo.name ="***"; 这样的方式设置对象值得时候,就会触发defineProperty这个里面的set方法。每当通过userInfo.name这个方式获取对象的值得时候就会触发defineProperty这个里面的get方法。

MVC和MVVM:

MVC :

Model-View-Controller 的缩写,就是 模型—视图—控制器,也就是说一个标准的Web 应用程式是由这三部分组成的:

View :用来把数据以某种方式呈现给用户

Model :其实就是数据

Controller :接收并处理来自用户的请求,并将 Model 返回给用户

MVC同时也会带来的问题:

1、 开发者在代码中大量调用相同的 DOM API,处理繁琐 ,操作冗余,使得代码难以维护。

2、大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。

3、 当 Model 频繁发生变化,开发者需要主动更新到View ;当用户的操作导致 Model 发生变化,开发者同样需要将变化的数据同步到Model 中,这样的工作不仅繁琐,而且很难维护复杂多变的数据状态。

MVVM:

MVVM 由 Model、View、ViewModel 三部分构成,Model 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转化成UI 展现出来,ViewModel 是一个同步View 和 Model的对象。

在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。

ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

关于同源策略:

目的:出于信息安全考虑。

同源条件:

协议相同 域名相同 端口相同 举例:www.example.com/dir/page.ht… 这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略),同源情况如下:

www.example.com/dir2/other.… example.com/dir/other.h… v2.www.example.com/dir/other.h… www.example.com:81/dir/other.h… www.example.com/dir/page.ht…

不同源的限制范围:

  1. 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB。
  2. 无法接触非同源网页的 DOM。
  3. 无法向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应)。

允许跨域行为实例:

* ``标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到。* ``标签嵌入CSS。由于CSS的[松散的语法规则](http://scarybeastsecurity.blogspot.dk/2009/12/generic-cross-browser-cross-domain.html),CSS的跨域需要一个设置正确的`Content-Type`消息头。不同浏览器有不同的限制: [IE](https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/gg622939%28v=vs.85%29), [Firefox](https://www.mozilla.org/en-US/security/advisories/mfsa2010-46/), [Chrome](http://code.google.com/p/chromium/issues/detail?id=9877), [Safari](https://support.apple.com/zh-cn/HT4070) 和 [Opera](https://www.opera.com/zh-cn/security/advisory/943)。* [``](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/img)嵌入图片。支持的图片格式包括PNG,JPEG,GIF,BMP,SVG* [``](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/video) 和 [``](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/audio)嵌入多媒体资源。* [``](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/object), [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed) 和 [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/applet)的插件。* [`@font-face`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/@font-face)引入的字体。一些浏览器允许跨域字体( cross-origin fonts),一些需要同源字体(same-origin fonts)。* [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frame)和[``](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/iframe)载入的任何资源。站点可以使用`X-Frame-Options`消息头来阻止这种形式的跨域交互</div> 跨域解决方案:

segmentfault.com/a/119000001…

1、 通过jsonp跨域

2、 document.domain + iframe跨域

3、 location.hash + iframe

4、 window.name + iframe跨域

5、 postMessage跨域

6、 跨域资源共享(CORS)

7、 nginx代理跨域

8、 nodejs中间件代理跨域

9、 WebSocket协议跨域

单点登录:

单点登录 SSO 全称 Singn Sign On 。SSO 指在多个应用系统中,用户只需要登录一次用户系统,就可以访问其他互相信任的应用系统。例如:在网易官网登录账户,那么再进入网易邮箱等其他业务的时候会自动登录。另外还有一个好处就是在一定时间内可以不用重复登录账户。

问题:

单点登录出现在二级域名的时候就不用跨域,可以通过cookie来共享登录信息。例如bbb.a.com 和 ccc.a.com 是二级域名。

单点登录出现在跨域里面比如(www.aaa.comwww.bbb.com):

一旦跨域就不能通过cookie来共享后台返回的登录信息。

这时就要通过postMessage来传递登录后返回的信息,比如token。得到来自不同域的信息后就可以实现单点登录了。

例子:

在a页面点击登陆过后,b页面直接影藏登录按钮,显示该用户已经登录。就不用再次登陆

a.html页面代码:

<title>A首页</title>
<meta charset="utf-8">
<p>
    <button onclick="login();" id="login">同步登录</button>
    <p id="msg" style="display: none;">该用户已经登录
        <button onclick="localStorage.clear();" id="login">注销</button>
    </p>
</p>

<iframe src="http://www.b.com" style="height: 0px;width: 0px;display: none;"></iframe>

<script>
// 是否显示“同步登录”按钮
var tokenData=localStorage.getItem('tokenData')
if(tokenData){
    document.getElementById('login').style.display='none';
    document.getElementById('msg').style.display='block';
}

// 同步登录
function login(){
    let data=JSON.stringify({
        msg:'建议以字符串形式传输字符串',
        token:'这是从后台而来的token'
    })
    document.getElementsByTagName('iframe')[0].contentWindow.postMessage(data,'*');
}

// 有消息从父级传来时 存贮 tokenData
window.addEventListener('message',function(e){
    if(e.source!=window.parent) return;
    localStorage.setItem("tokenData",e.data);
},false);
</script>

b.html页面代码:

<title>B首页</title>
<meta charset="utf-8">
<p>
    <button onclick="login();" id="login">同步登录</button>
    <p id="msg" style="display: none;">该用户已经登录
        <button onclick="localStorage.clear();" id="login">注销</button>
    </p>
</p>

<iframe src="http://www.a.com" style="height: 0px;width: 0px;display: none;"></iframe>

<script>
// 是否显示“同步登录”按钮
var tokenData=localStorage.getItem('tokenData')
if(tokenData){
    document.getElementById('login').style.display='none';
    document.getElementById('msg').style.display='block';
}

// 同步登录
function login(){
    let data=JSON.stringify({
        msg:'建议以字符串形式传输字符串',
        token:'这是从后台而来的token'
    })
    document.getElementsByTagName('iframe')[0].contentWindow.postMessage(data,'*');
}

// 有消息从父级传来时 存贮 tokenData
window.addEventListener('message',function(e){
    if(e.source!=window.parent) return;
    localStorage.setItem("tokenData",e.data);
},false);
</script>

各种上传问题:

掘金:

juejin.cn/post/684490…

github:

我的关注/

别人的优秀代码:github.com/Bigerfe/fe-…