你所不知道的 CSS 阴影技巧与细节 滚动视差?CSS 不在话下 神奇的选择器 :focus-within 当角色转换为面试官以后 NPOI 教程 - 3.2 打印相关设置 前端XSS相关整理 委托入

你所不知道的 CSS 阴影技巧与细节

 

关于 CSS 阴影,以前已经有写过一篇,box-shadow 与 filter:drop-shadow 详解及奇技淫巧,介绍了一些关于 box-shadow 的用法。javascript

最近一个新的项目,CSS-Inspiration,挖掘了其余不少有关 CSS 阴影的点子,是以前的文章没有覆盖到的新内容,并且有一些颇有意思,遂打算再起一篇。php

本文的题目是 CSS 阴影技巧与细节。CSS 阴影,却不必定是 box-shadow 与 filter:drop-shadow,为啥?由于使用其余属性也能够模拟阴影,并且是各类各样的阴影。下面且听我娓娓道来~
dp q2w17km a5m p35css

 

单侧投影

先说单侧投影,关于 box-shadow,大部分时候,咱们使用它都是用来生成一个两侧的投影,或者一个四侧的投影。以下:html

image

OK,那若是要生成一个单侧的投影呢?前端

咱们来看看 box-shadow 的用法定义:java

1
2
3
{
     box-shadow:  none  | [ inset ? && [ <offset-x> <offset-y> <blur-radius>? <spread-radius>? <color>? ] ]#
}

以 box-shadow: 1px 2px 3px 4px #333 为例,4 个数值的含义分别是,x 方向偏移值、y 方向偏移值 、模糊半径、扩张半径。react

这里有一个小技巧,扩张半径能够为负值。css3

继续,若是阴影的模糊半径,与负的扩张半径一致,那么咱们将看不到任何阴影,由于生成的阴影将被包含在原来的元素之下,除非给它设定一个方向的偏移量。因此这个时候,咱们给定一个方向的偏移值,便可实现单侧投影:git

image

CodePen Demo -- css单侧投影github

  

投影背景 / 背景动画

接着上面的说。

很明显,0 = -0,因此当 box-shadow 的模糊半径和扩张半径都为 0 的时候,咱们也能够获得一个和元素大小同样的阴影,只不过被元素自己遮挡住了,咱们尝试将其偏移出来。

CSS代码以下:

1
2
3
4
5
6
7
div {
     width 80px ;
     height 80px ;
     border 1px  solid  #333 ;
     box-sizing: border-box;
     box-shadow:  80px  80px  0  0  #000 ;
}

获得以下结果:

image

有什么用呢?好像没什么意义啊。

额,确实好像没什么用。不过咱们注意到,box-shadow 是能够设置多层的,也就是多层阴影,并且能够进行过渡变换动画(补间动画)。可是 background-image: linear-gradient(),也就是渐变背景是不能进行补间动画的。

这又扯到哪里去了。好咱们回来,利用上面的特性,咱们能够利用 box-shadow 实现本来只能利用渐变才能实现的背景图:

image

用 box-shadow,实现它的 CSS 代码以下(能够更简化):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.shadow {
     position relative ;
     width 250px ;
     height 250px ;
}
 
.shadow::before {
     content "" ;
     position absolute ;
     width 50px ;
     height 50px ;
     top -50px ;
     left -50px ;
     box-shadow:
         50px  50px  #000 150px  50px  #000 250px  50px  #000 ,
         50px  100px  #000 150px  100px  #000 250px  100px  #000 ,
         50px  150px  #000 150px  150px  #000 250px  150px  #000 ,
         50px  200px  #000 150px  200px  #000 250px  200px  #000 ,
         50px  250px  #000 150px  250px  #000 250px  250px  #000 ;
}

用渐变来实现的话,只须要这样:

1
2
3
4
5
6
.gradient {
     width 250px ;
     height 250px ;
     background-image : linear-gradient( 90 deg,  #000  0% #000  50% #fff  50% #fff  100% );
     background- size :   100px  100px ;
}

为何选择更为复杂的 box-shadow 呢?由于它能够进行补间动画,像这样,这是使用渐变作不到的:

bgshadow

CodePen Demo -- box-shadow实现背景动画

固然,这只是个示例 Demo,运用点想象力还有不少有意思的效果,再贴一个:

bgshadow2

CodePen Demo -- CSS Checker Illusion( By David Khourshid )

嗯,颇有意思,就是实际用途可能不大。

qq 20181031140253

 

立体投影

好,咱们继续。下一个主题是立体投影。

这个说法很奇怪,阴影的出现,本就是为了让本来的元素看起来更加的立体,那这里所谓的立体投影,是个怎么立体法?

这里所谓的立体投影,并不必定是使用了 box-shadowtext-shadow 或者 drop-shadow,而是咱们使用其余元素或者属性模拟元素的阴影。而这样作的目的,是为了可以突破 box-shadow 这类元素的一些定位局限。让阴影的位置、大小、模糊度能够更加的灵活。

OK,让咱们来看看,这样一个元素,咱们但愿经过自定义阴影的位置,让它更加立体:

image

上图 div 只是带了一个很是浅的 bos-shadow ,看上去和立体没什么关系,接下来,咱们经过 div 的伪元素,给它生成一个和原图边角形状相似的图形,再经过 transform 位移一下,多是这样:

image

OK,最后对这个用伪元素生成的元素进行一些虚化效果(filter或者box-shadow均可以),就能够实现一个边角看起来像被撕开的立体效果:

image

代码很是简单,伪 CSS 代码示意以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
div {
     position relative ;
     width 600px ;
     height 100px ;
     background : hsl( 48 100% 50% );
     border-radius:  20px ;
}
 
div::before {
     content "" ;
     position absolute ;
     top 50% ;
     left 5% ;
     right 5% ;
     bottom 0 ;
     border-radius:  10px ;
     background : hsl( 48 100% 20% );
     transform: translate( 0 -15% ) rotate( -4 deg);
     transform-origin:  center  center ;
     box-shadow:  0  0  20px  15px  hsl( 48 100% 20% );
}

因此总结一下:

  • 立体投影的关键点在于利于伪元素生成一个大小与父元素相近的元素,而后对其进行 rotate 以及定位到合适位置,再赋于阴影操做
  • 颜色的运用也很重要,阴影的颜色一般比自己颜色要更深,这里使用 hsl 表示颜色更容易操做,l 控制颜色的明暗度

还有其余不少场景:

CodePen Demo -- 立体投影

 

文字立体投影 / 文字长阴影

上面的立体效果在文字上就彻底不适用了,因此对待文字的立体阴影效果,还须要另辟蹊径。

正常而言,咱们使用 text-shadow 来生成文字阴影,像这样:

1
2
3
4
5
<div> Txt Shadow</div>
-----
div {
     text-shadow 6px  6px  3px  hsla( 14 100% 30% 1 );
}

image

嗯,挺好的,就是不够立体。那么要作到立体文字阴影,最多见的方法就是使用多层文字阴影叠加。

Tips:和 box-shadow 同样,text-shadow 是能够叠加多层的!可是对于单个元素而言, drop-shadow的话就只能是一层。

好,上面的文字,咱们试着叠加个 50 层文字阴影试一下。额,50 层手写,其实很快的~
image

好吧,手写真的太慢了,还容易出错,因此这里咱们须要借助一下 SASS/LESS 帮忙,写一个生成 50 层阴影的 function 就好,咱们每向右和向下偏移 1px,生成一层 text-shadow:

1
2
3
4
5
6
7
8
9
10
11
12
13
@function makeLongShadow($color) {
     $val:  0px  0px  $color;
 
     @for $i from  1  through  50  {
         $val: #{$val}, #{$i}px #{$i}px #{$color};
     }
 
     @return $val;
}
 
div {
     text-shadow : makeLongShadow(hsl( 14 100% 30% ));
}

上面的 SCSS 代码。通过编译后,就会生成以下 CSS:

1
2
3
div {
       text-shadow 0px  0px  #992400 1px  1px  #992400 2px  2px  #992400 3px  3px  #992400 4px  4px  #992400 5px  5px  #992400 6px  6px  #992400 7px  7px  #992400 8px  8px  #992400 9px  9px  #992400 10px  10px  #992400 11px  11px  #992400 12px  12px  #992400 13px  13px  #992400 14px  14px  #992400 15px  15px  #992400 16px  16px  #992400 17px  17px  #992400 18px  18px  #992400 19px  19px  #992400 20px  20px  #992400 21px  21px  #992400 22px  22px  #992400 23px  23px  #992400 24px  24px  #992400 25px  25px  #992400 26px  26px  #992400 27px  27px  #992400 28px  28px  #992400 29px  29px  #992400 30px  30px  #992400 31px  31px  #992400 32px  32px  #992400 33px  33px  #992400 34px  34px  #992400 35px  35px  #992400 36px  36px  #992400 37px  37px  #992400 38px  38px  #992400 39px  39px  #992400 40px  40px  #992400 41px  41px  #992400 42px  42px  #992400 43px  43px  #992400 44px  44px  #992400 45px  45px  #992400 46px  46px  #992400 47px  47px  #992400 48px  48px  #992400 49px  49px  #992400 50px  50px  #992400 ;
}

看看效果:

image

额,很不错,很立体。可是,就是丑,并且说不上来的奇怪。

问题出在哪里呢,阴影实际上是存在明暗度和透明度的变化的,因此,对于渐进的每一层文字阴影,明暗度和透明度应该都是不断变化的。这个需求,SASS 能够很好的实现,下面是两个 SASS 颜色函数:

  • fade-out 改变颜色的透明度,让颜色更加透明
  • desaturate 改变颜色的饱和度值,让颜色更少的饱和

关于 SASS 颜色函数,能够看看这里:Sass基础—颜色函数

咱们使用上面两个 SASS 颜色函数修改一下咱们的 CSS 代码,主要是修改上面的 makeLongShadow function 函数:

1
2
3
4
5
6
7
8
9
10
@function makelongrightshadow($color) {
     $val:  0px  0px  $color;
 
     @for $i from  1  through  50  {
         $ color : fade-out(desaturate($color,  1% ), . 02 );
         $val: #{$val}, #{$i}px #{$i}px #{$color};
     }
 
     @return $val;
}

好,看看最终效果:

image

嗯,大功告成,此次顺眼了不少~

CodePen Demo -- 立体文字阴影

固然,使用 CSS 生成立体文字阴影的方法还有不少,下面再贴出一例,使用了透明色叠加底色的多重线性渐变实现的文字立体阴影,感兴趣的同窗能够去看看具体实现:

线性渐变配合阴影实现条纹立体阴影条纹字

  

长投影

上面提到了经过多层阴影叠加实现文字的立体阴影。运用在 div 这些容器上也是能够的。固然这里还有一种挺有意思的方法。假设咱们,有一个矩形元素,但愿给他添加一个长投影,像下面这样:

image

要生成这种长投影,刚刚说的叠加多层阴影能够,再就是借助元素的两个伪元素,其实上面的图是这样的:

image

关键点在于,咱们经过对两个伪元素的 transform: skew() 变换以及从实色到透明色的背景色变化,实现了长投影的效果:

CodePen Demo -- 线性渐变模拟长阴影

 

彩色投影

一般而言,咱们生成阴影的方式大可能是 box-shadow 、filter: drop-shadow() 、text-shadow 。可是,使用它们生成的阴影一般只能是单色或者同色系的。

你这么说,难道还能够生成渐变色的阴影不成?
image

额,固然不行。

image

这个真不行,可是经过巧妙的利用 filter: blur 模糊滤镜,咱们能够伪装生成渐变色或者说是颜色丰富的阴影效果。

假设咱们有下述这样一张头像图片:

image

下面就利用滤镜,给它添加一层与原图颜色相仿的阴影效果,核心 CSS 代码以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.avator {
     position relative ;
     background url ($img)  no-repeat  center  center ;
     background- size 100%  100% ;
     
     &::after {
         content "" ;
         position absolute ;
         top 10% ;
         width 100% ;
         height 100% ;
         background : inherit;
         background- size 100%  100% ;
         filter: blur( 10px ) brightness( 80% ) opacity(. 8 );
         z-index -1 ;
     }
}

看看效果:

image

其简单的原理就是,利用伪元素,生成一个与原图同样大小的新图叠加在原图之下,而后利用滤镜模糊 filter: blur() 配合其余的亮度/对比度,透明度等滤镜,制做出一个虚幻的影子,假装成原图的阴影效果。

嗯,最重要的就是这一句 filter: blur(10px) brightness(80%) opacity(.8); 。

CodePen Demo -- filter create shadow

 

使用 box-shadow 实现的灯光效果

好,上文主要是一些实现各类阴影的方法,接下来是效果篇。先来看看使用 box-shadow实现的一些灯光效果。 

 

box-shadow 实现霓虹氖灯文字效果

这个效果也叫 Neon,Codepen 上有不少相似的效果,本质上都是大范围的 box-shadow 过渡效果与白色文字的叠加:

lightshadow

CodePen Demo -- box-shadow实现霓虹氖灯文字效果

 

使用box-shadow实现阴影灯光show

和上面的效果相似,本质上都是多重阴影的过渡效果,或许再来点 3D 效果?

合理搭配,效果更佳:

lightshadow

CodePen Demo -- 使用box-shadow实现阴影灯光show

 

 

使用 drop-shadow | box-shadow 实现单标签抖音 LOGO

嗯哼,既然标题叫你所不知道的 CSS 阴影技巧与细节,那么本文也应该有一点奇技淫巧。

先来看这个,单个标签实现仿抖音 LOGO,固然因为限定在一个元素,因此细节方面仍是有不少瑕疵。

想着仿的原因是某天刷抖音的时候看见这个 LOGO 的一时兴起,CSS 写多了,看见什么东西都会条件反射的想这个能不能用 CSS 实现。

咱们先来看看抖音的 LOGO:

image

其实很简单,主体实际上是由3个颜色不一样相似 J 的形状组成。而单独拎出一个,又能够把它分红四分之三圆、|以及㇏组成。

正好,一个元素加上它的两个伪元素,恰好能够凑成这三个形状,咱们试着实现如下,简单 CSS 代码以下:

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
<div></div>
---
div {
     position relative ;
     width 37px ;
     height 218px ;
     background #fff ;
 
     &::before {
         content "" ;
         position absolute ;
         width 100px ;
         height 100px ;
         border 37px  solid  #fff ;
         border-top 37px  solid  transparent ;
         border-radius:  50% ;
         top 123px ;
         left -137px ;
         transform: rotate( 45 deg);
     }
     
         &::after {
         content "" ;
         position absolute ;
         width 140px ;
         height 140px ;
         border 30px  solid  #fff ;
         border-right 30px  solid  transparent ;
         border-top 30px  solid  transparent ;
         border-left 30px  solid  transparent ;
         top -100px ;
         right -172px ;
         border-radius:  100% ;
         transform: rotate( 45 deg);
     }
}

上面的代码就能够生成整个形状的主体:
image

接下来就是轮到 filter: drop-shadow() 登场,它能够在元素呈现以前,为元素的渲染提供一些效果,最多见的也就用它渲染总体阴影。咱们一般会用它来实现对话框的小三角与整个对话框的阴影效果,像下面这样,左边是使用 drop-shadow 的效果,右边是使用普通 box-shadow的效果。

image

本文假定读者已经了解了 drop-shadow 的基本用法,上图效果来自这里:CodePen Demo -- Drop-shadow vs box-shadow (2) By Kseso

OK,回到咱们正文,下面咱们使用 filter: drop-shadow() 生成它的第一层左边的蓝色阴影,添加在主体 div:

1
2
3
4
5
6
7
8
9
10
11
12
div {
     position relative ;
     width 37px ;
     height 218px ;
     background #fff ;
     filter:drop-shadow( -10px  -10px  0  #24f6f0 );
 
    &::before,
    &::after {
     ...
     }
}

获得以下效果:
image

好,接下来咱们只须要再添加一层红色 filter: drop-shadow() 在右侧就大功告成!

等等!哪里不对,上面我也有提到过, 和 box-shadow 同样,text-shadow 是能够叠加多层的!可是对于单个元素而言, drop-shadow 的话就只能是一层。

也就是说,没法在 div 上再使用 filter: drop-shadow() 生成另外一侧的红色投影,不过还好,咱们还有两个伪元素的filter: drop-shadow() 以及 box-shadow 尚未用上,通过一番尝试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
div {
     position relative ;
     width 37px ;
     height 218px ;
     background #fff ;
     filter:drop-shadow( -10px  -10px  0  #24f6f0 ) contrast( 150% ) brightness( 110% );
     box-shadow:  11.6px  10px  0  0  #fe2d52 ;
     
     &::before {
         ....
         filter: drop-shadow( 16px  0px  0  #fe2d52 );
     }
     
     &::after {
         ....
         filter:drop-shadow( 14px  0  0  #fe2d52 );
     }
}

咱们分别再利用 div 的 box-shadow 以及两个伪元素的 filter: drop-shadow() ,在单个标签的限制下,最终结果以下:

image

CodePen Demo -- 单标签实现抖音LOGO

总结一下:

  • 主要借助了两个伪元素实现了总体结构,借助了 drop-shadow 生成一层总体阴影
  • drop-shadow 只能是单层阴影,因此另外一层阴影须要多尝试
  • contrast(150%) brightness(110%) 则能够加强图像的对比度和亮度,更贴近抖音LOGO的效果

 

固然,关于 CSS 阴影还有不少有意思的技巧和细节,本文限于篇幅再也不一一罗列。

我在 Git 上开了个仓库,CSS-Inspiration,以分类的形式,展现不一样 CSS 属性或者不一样的课题使用 CSS 来解决的各类方法。更多有意思的 CSS 技巧能够在这里找到,并且是每日更新。

 

最后

感谢耐心读完。更多精彩 CSS 技术文章汇总在个人 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

好了,本文到此结束,但愿对你有帮助 :)

若是还有什么疑问或者建议,能够多多交流,原创文章,文笔有限,才疏学浅,文中如有不正之处,万望告知。

 

 

滚动视差?CSS 不在话下

 

何为滚动视差

视差滚动(Parallax Scrolling)是指让多层背景以不一样的速度移动,造成立体的运动效果,带来很是出色的视觉体验。 做为网页设计的热点趋势,愈来愈多的网站应用了这项技术。

parallax

一般而言,滚动视差在前端须要辅助 Javascript 才能实现。固然,其实 CSS 在实现滚动视差效果方面,也有着不俗的能力。下面就让咱们来见识一二:

 

认识 background-attachment

background-attachment 算是一个比较生僻的属性,基本上平时写业务样式都用不到这个属性。可是它自己颇有意思。

background-attachment:若是指定了 background-image ,那么 background-attachment 决定背景是在视口中固定的仍是随着包含它的区块滚动的。

单单从定义上有点难以理解,随下面几个 Demo 了解下 background-attachment 究竟是什么意思:

background-attachment: scroll

scroll 此关键字表示背景相对于元素自己固定, 而不是随着它的内容滚动。

background-attachment: local

local 此关键字表示背景相对于元素的内容固定。若是一个元素拥有滚动机制,背景将会随着元素的内容滚动, 而且背景的绘制区域和定位区域是相对于可滚动的区域而不是包含他们的边框。

background-attachment: fixed

fixed 此关键字表示背景相对于视口固定。即便一个元素拥有滚动机制,背景也不会随着元素的内容滚动。

注意一下 scroll 与 fixed,一个是相对元素自己固定,一个是相对视口固定,有点相似 position 定位的 absolute 和 fixed

能够感觉下 3 种不一样取值的不一样效果:

CodePen Demo -- bg-attachment Demo

 

使用 background-attachment: fixed 实现滚动视差

首先,咱们使用 background-attachment: fixed 来实现滚动视差。fixed 此关键字表示背景相对于视口固定。即便一个元素拥有滚动机制,背景也不会随着元素的内容滚动。

这里的关键在于,即便一个元素拥有滚动机制,背景也不会随着元素的内容滚动。也就是说,背景图从一开始就已经被固定死在初始所在的位置。

咱们使用,图文混合排布的方式,实现滚动视差,HTML 结构以下,.g-word 表示内容结构,.g-img 表示背景图片结构:

1
2
3
4
5
6
7
< section  class="g-word">Header</ section >
< section  class="g-img">IMG1</ section >
< section  class="g-word">Content1</ section >
< section  class="g-img">IMG2</ section >
< section  class="g-word">Content2</ section >
< section  class="g-img">IMG3</ section >
< section  class="g-word">Footer</ section >

关键 CSS:

1
2
3
4
5
6
7
8
9
10
section {
     height 100 vh;
}
 
.g-img {
     background-image url (...);
     background-attachment fixed ;
     background- size : cover;
     background-position center  center ;
}

效果以下:

parallax background-attachment: fixed

CodePen Demo -- https://codepen.io/Chokcoco/pen/JBaQoY

嗯?有点神奇,为何会是这样呢?可能不少人会和我同样,第一次接触这个属性对这样的效果感到懵逼。

咱们把上面 background-attachment: fixed 注释掉,或者改成 background-attachment: local,再看看效果:

parallax background-attachment: fixed 2

CodePen Demo -- bg-attachment:local

此次,图片正常跟随滚动条滚动了,按常理,这种效果才符合咱们大脑的思惟。

而滚动视差效果,正是不按常理出牌的一个效果,重点来了:

当页面滚动到图片应该出现的位置,被设置了 background-attachment: fixed 的图片并不会继续跟随页面的滚动而跟随上下移动,而是相对于视口固定死了。

好,咱们再来试一下,若是把全部 .g-word 内容区块都去掉,只剩下所有设置了 background-attachment: fixed 的背景图区块,会是怎么样呢?

HTML 代码以下:

1
2
3
< section  class="g-img">IMG1</ section >
< section  class="g-img">IMG2</ section >
< section  class="g-img">IMG3</ section >
1
2
3
4
5
6
7
8
9
10
section {
     height 100 vh;
}
 
.g-img {
     background-image url (...);
     background-attachment fixed ;
     background- size : cover;
     background-position center  center ;
}

效果以下:

parallax background-attachment: fixed 3

CodePen Demo

结合这张 GIF,相信能对 background-attachment: fixed 有个更深入的认识,移动的只有视口,而背景图是一直固定死的。

综上,就是 CSS 使用 background-attachment: fixed 实现滚动视差的一种方式,也是相对而言比较容易的一种。固然,background-attachment: fixed 自己的效果并不只只是能有用来实现滚动视差效果,合理运用,还能够实现其余不少有趣的效果,这里简单再列一个:

 

background-attachment: fixed 实现图片点击水纹效果

利用图片相对视口固定,能够有不少有趣的效果,譬以下面这个,来源于这篇文章CSS Water Wave (水波效果)

background-attachment: fixed Wave

CodePen Demo -- bg-attachment:fixed Wave

利用图片相对视口固定的特性实现点击的水纹效果。

上面这个效果有点瑕疵,图片在放大容器变大的过程当中发生了明显的抖动。固然,效果仍是能够的,background-attachment 还有不少有意思的效果能够挖掘。

 

使用 transform: translate3d 实现滚动视差

言归正传,下面介绍另一种使用 CSS 实现的滚动视差效果,利用的是 CSS 3D。

原理就是:

  1. 咱们给容器设置上 transform-style: preserve-3d 和 perspective: xpx,那么处于这个容器的子元素就将位于3D空间中,

  2. 再给子元素设置不一样的 transform: translateZ(),这个时候,不一样元素在 3D Z轴方向距离屏幕(咱们的眼睛)的距离也就不同

  3. 滚动滚动条,因为子元素设置了不一样的 transform: translateZ(),那么他们滚动的上下距离 translateY 相对屏幕(咱们的眼睛),也是不同的,这就达到了滚动视差的效果。

关于 transform-style: preserve-3d 以及 perspective 本文不作过多篇幅展开,默认读者都有所了解,还不是特别清楚的,能够先了解下 CSS 3D。

核心代码表示就是:

1
2
3
4
5
< div  class="g-container">
     < div  class="section-one">translateZ(-1)</ div >
     < div  class="section-two">translateZ(-2)</ div >
     < div  class="section-three">translateZ(-3)</ div >
</ div >
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
html {
     height 100% ;
     overflow hidden ;
}
 
body {
     perspective:  1px ;
     transform-style: preserve -3 d;
     height 100% ;
     overflow-y:  scroll ;
     overflow-x:  hidden ;
}
 
.g-container {
     height 150% ;
 
     .section-one {
         transform: translateZ( -1px );
     }
     .section-two {
         transform: translateZ( -2px );
     }
     .section-three {
         transform: translateZ( -3px );
     }
}

总结就是父元素设置 transform-style: preserve-3d 和 perspective: 1px,子元素设置不一样的 transform: translateZ,滚动滚动条,效果以下:

css3dparallax

CodePen Demo -- CSS 3D parallax

很明显,当滚动滚动条时,不一样子元素的位移程度从视觉上看是不同的,也就达到了所谓的滚动视差效果。

滚动视差文字阴影/虚影效果

那么,运用 translate3d 的视差效果,又能有一些什么好玩的效果呢?下面这个滚动视差文字阴影/虚影效果颇有意思:

csstparallax

CodePen Demo -- CSS translate3d Parallax

固然,经过调整参数(perspective: ?px 以及 transform: translateZ(-?px);),还能有其余颇有意思的效果出现:

csstparallax2

CodePen Demo -- CSS translate3d Parallax 2

是否是颇有电影开片的厂商 LOGO 的特效的感受 joy 。

师父领进门,修行在我的,怎么制做更好更有意思的效果仍是须要花时间钻研和琢磨,这里我仅仅是抛砖引玉,但愿能见到更多 Nice 的效果。

 

最后

感谢耐心读完。更多精彩 CSS 技术文章汇总在个人 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

好了,本文到此结束,但愿对你有帮助 :)

若是还有什么疑问或者建议,能够多多交流,原创文章,文笔有限,才疏学浅,文中如有不正之处,万望告知。

 

 

神奇的选择器 :focus-within

 

CSS 的伪类选择器和伪元素选择器,让 CSS 有了更为强大的功能。

伪类你们听的多了,伪元素可能听到的不是那么频繁,其实 CSS 对这两个是有区分的。

有个错误有必要每次讲到伪类都提一下,有时你会发现伪类元素使用了两个冒号 (::) 而不是一个冒号 (:),这是 CSS3 规范中的一部分要求,目的是为了区分伪类和伪元素,大多数浏览器都支持下面这两种表示方式。

一般而言,

1
2
3
4
5
6
7
#id:after{
  ...
}
 
#id::after{
...
}

符合标准而言,单冒号(:)用于 CSS3 伪类,双冒号(::)用于 CSS3 伪元素。

固然,也有例外,对于 CSS2 中已经有的伪元素,例如 :before,单冒号和双冒号的写法 ::before 做用是同样的。

因此,若是你的网站只须要兼容 webkit、firefox、opera 等浏览器或者是移动端页面,建议对于伪元素采用双冒号的写法,若是不得不兼容低版本 IE 浏览器,仍是用 CSS2 的单冒号写法比较安全。

 

伪类选择器 :focus-within

言归正传,今天要说的就是:focus-within 伪类选择器。

它表示一个元素得到焦点,或,该元素的后代元素得到焦点。划重点,它或它的后代得到焦点。

这也就意味着,它或它的后代得到焦点,均可以触发 :focus-within

:focus-within 的冒泡性

这个属性有点相似 Javascript 的事件冒泡,从可获焦元素开始一直冒泡到根元素 html,均可以接收触发 :focus-within 事件,相似下面这个简单的例子这样:

1
2
3
4
5
< div  class="g-father">
     < div  class="g-children">
         < input  type="button" value="Button">
     </ div >
</ div >
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
html,
body,
.g-father,
.g-children {
     padding 30px ;
     border : 1px  solid  #999 ;
}
 
input {
     ...
     &:focus {
         background #00bcd4 ;
     }
}
 
html:focus-within {
     background #e91e63 ;
}
body:focus-within {
     background #ff5722 ;
}
.g-father:focus-within {
     background #ffeb3b ;
}
.g-children:focus-within {
     background #4caf50 ;
}

就是这样:

focuswithinmaopao

CodePen Demo -- :focus-within 冒泡触发

这个选择器的存在,让 CSS 有了进一步的让元素持久停留在一种新状态的的能力。

下面几个例子,看看 :focus-within 能够提供什么能力,作些什么事情。

 

感应用户聚焦区域

它或它的后代得到焦点,这一点使得让感知获焦区域变得更大,因此,最常规的用法就是使用 :focus-within 感应用户操做聚焦区域,高亮提醒。

下面的效果没有任何 JS 代码:

cssfocuswithinpesudo

这里是什么意思呢?:focus-within 作了什么呢?

  • 咱们无须去给获焦的元素设置 :focus 伪类,而是能够给须要的父元素设置,这样当元素获焦时,我能够一并控制它的父元素的样式

核心思想用 CSS 代码表达出来大概是这样:

1
2
3
4
5
6
7
8
< div  class="g-container">
     < div  class="g-username">
         < input  type="text" placeholder="user name" class="g_input" >
     </ div >
     < div  class="g-username">
         < input  type="text" placeholder="code" class="g_input" >
     </ div >
</ div >
1
2
3
4
5
6
7
.g-container:focus-within {
     ...
 
     input {
         ....
     }
}

DEMO -- CSS focus-within INPUT

运用上面思想,咱们能够把效果作的更炫一点点,在某些场景制做一些加强用户体验的效果:

purecssfocus

DEMO -- PURE CSS FOCUS By :focus-within

 

TAB导航切换

在以前的一篇文章里,介绍了两种纯 CSS 实现的 TAB 导航栏切换方法:

纯CSS的导航栏Tab切换方案

如今又多了一种方式,利用了 :focus-within 能够在父节点获取元素得到焦点的特性,实现的TAB导航切换:

focuswithintab

DEMO -- focus-within switch tab

主要的思路就是经过获焦态来控制其余选择器,以及最重要的是利用了父级的 :not(:focus-within) 来设置默认样式:

1
2
3
4
5
6
7
8
9
10
11
.nav-box:not(:focus-within) {
     // 默认样式
}
 
.nav-A:focus-within ~ .content-box .content-A {
     display block ;
}
 
.nav-B:focus-within ~ .content-box .content-B {
     display block ;
}

 

配合 :placeholder-shown 伪类实现表单效果

:focus-within 一我的能力有限,一般也会配合其余伪类实现一些不错的效果。这里要再简单介绍的是另一个有意思的伪类 :placeholder-shown

:placeholder-shown:The :placeholder-shown CSS pseudo-class represents any or <textarea> element that is currently displaying placeholder text.

另外,划重点,这个伪类是仍处于实验室的方案。也就是未归入标准,固然咱们的目的是探寻有意思的 CSS 。

意思大概就是,当 input 类型标签使用了 placeholder 属性有了默认占位的文字,会触发此伪类样式。配合:not()伪类,能够再改变当默认文字消失后的样式,再配合本文的主角,咱们能够实现表单的一系列效果。

CSS 代码大概呈现成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.g-container {
     width 500px ;
     height 60px ;
 
     input {
         height 100% ;
         width 100% ;
 
         &:not(:placeholder-shown) {
             ...
         }
 
         &:placeholder-shown {
             ...
         }
     }
 
     &:focus-within {
         ...
     }
}

实际效果以下:

placeholder

能够看到,上面的效果没有用到任何 JS,能够实现:

  1. 整个 input(包括父元素所在区域)获焦与非获焦样式控制
  2. placeholder 属性设置的文字出现与消失后样式控制

CodePen Demo -- :placeholder-shown && :focus-within

 

实现离屏导航

这个是其余不少文章都有提到过的一个功能,利用 focus-within 便捷的实现离屏导航,能够说将这个属性的功能发挥的淋漓尽致,这里我直接贴一个 codepen 上 Dannie Vinther 对这个效果的实现方案:

offscreennav

CodePen Demo -- Off-screen nav with :focus-within [PURE CSS]

 

实现掘金登陆动效切换

juejin.im是我很喜欢的一个博客网站,它的登陆有一个小彩蛋,最上面的熊猫在你输入账号密码的时候会有不一样的状态,效果以下:

juejin

利用本文所讲的 focus-within ,能够不借助任何 Javascript,实现这个动效:

juejinfocuswithin

感兴趣的能够戳这里看看完整的Demo代码:

CodePen Demo -- 掘金登陆效果纯CSS实现

 

兼容性

好了,例子举例的也差很少了,下面到了杀人诛心的兼容性时刻,按照惯例,这种属性大几率是一片红色,看看 CANIUSE,截图日期(2018/08/02),其实也还不算特别惨淡。

image

 

 

一. 面试官须要作到三件事

1. 本身复习好或去学一下相关技术点

没错,面试官也是须要准备的。要防止理解不来候选人的技术,也为了可以hold住现场。

2. 想一些要问的问题,想好怎么评判候选人

问题的选择还要有连贯性,更进一步地,还要预先想到候选人可能会怎么答,本身要怎么接。做为面试官,最好提问要思路清晰不要断。

3. 想好怎么在面试过程当中记录重点的讨论,用以佐证面试结果

 

2、怎么考察校招候选人

在咱们这边,初面通常会限制在15分钟左右,要在这么短期内考察一我的是有点难的,因此要抓好关键点。

对于应届校招生来讲,我我的会从这四个角度考察

1. 计算机基础

对于在校生来讲,会比较看重基础,数据结构、算法、网络、操做系统 这些仍是会涉及的,但不会太难。

社招有另外的玩法,另外,在校的暑期实习生会下降一些要求

基本都会从如下抽几个来问问,前端基础和项目经验失分的话,这里就是得分点了

数据结构:栈和队列的区别,JS里面的栈和队列,二叉树的几种遍历方式(高级)

算法:二分查找,冒泡排序,插入排序,快排(高级),深度/广度优先搜索(高级)

网络:OSI七层模型,HTTP/TCP在哪一层,HTTP和HTTPS区别,HTTP三次握手和四次挥手,常见状态码和首部字段,GET和POST区别,HTTPS链接过程(高级),了解HTTP2么(高级)

操做系统:进程和线程的区别

 

2. 前端基础

虽然对在校生看重基础,也不表明不看重前端的专业基础。毕竟你是要作前端的,就应该有所准备。

问题首先会选前面三个基础的,而后会根据候选人用过的技术、框架来调整,通常都会问为何要用XX技术,XX技术相比起来有什么优势。

HTML:怎么理解语义化标准化,HTML5新增的特性(别只会说新标签,我但愿你能说出新的API)

CSS: 垂直居中的实现,position属性值的区别,浮动的问题和解决,怎么用CSS画圆画三角形,Flex布局用过没,rem是什么以及和em的区别(高级),BFC(高级),内联盒模型(高级),CSS动画的简单使用

JS: 闭包是什么以及特色,怎么继承举个栗子,做用域是什么举个栗子,setTimeout/setInterval区别,了解过哪些事件(不少人把双击事件说成是doubleclick),原生获取DOM元素(但愿能说出新的API)、获取元素宽高方式,clientHeight/offsetHeight/scrollHeight区别(高级),在元素后面放元素(高级)

ES6:用过哪些新特性,let和var区别,Promise状态及为何用它,箭头函数this指向

jQuery: 链式调用怎么实现,有看过源码么(说一下知道有哪些实现),它有什么缺点

bootstrap: 为何用它(但愿能说出响应式),简单说几个用法,本身能够实现栅格化么(高级)

NodeJS:它有什么特色,为何不用其余后台语言

Webpack:有本身配置过么,loader和plugins的区别,和gulp/grunt的区别

综合:前端安全的认识,前端优化的方法,强制缓存/协商缓存相关,cookie和session,websocket和http区别(不用它则怎么实现实时),url从输入到页面渲染的过程(dns解析过关,DOM构建过程加分,浏览器进线程加加分)

框架:为何用Angular/React/Vue/Redux/Vuex(说出特色,它们解决了什么问题),生命周期,setState不保证同步,组件间通讯

其余: ...

 

3. 项目经验

项目经验主要考察候选人的实践,以及解决问题能力。通常来讲一个项目太少了,列2-4个比较好,太多也看不了那么多

作过的最好的项目是什么,这个项目里面用到什么技术(期间会从关键词展开问技术点)

在项目里面遇到过什么棘手的问题没,怎么解决的(但愿不要只说百度搜索)

若是让你优化这个项目,你以为能够怎么改进

 

这个部分也包括过往在公司里面的实习经历

实习期间作的是什么,有什么收获

实习期间的开发流程

 

若是前面技术基础和前端基础答得不错了,这个部分就不会问太多了,由于时间不够用,且通常也会放在下一轮面试中细问。

若是前面都答得很差,若是项目经历这个部分有优点,仍是有但愿的。

 

4. 综合能力

态度,有没有迟到

会稍稍关注专业课的成绩(不必定)

学前端多久了,怎么学的,看过哪些书,有没有技术总结

我的优势/缺点

关注技术热情,职业规划有没有

沟通顺不畅(要注意反应不要太迟钝,本身注意何时该收口了),思惟条理清晰与否

 

上面列举了这么多想要问的问题,问题是列举不完的,时间限制也不容许问那么多,也不必,因此会从各方面抽取几个问题来问。

 

首先,我会点几个计算机基础,而后着重问前端基础,若是前端基础挺好,就再过一下项目经验,不出差错基本就经过了。

若是前端基础和项目经验这块挺通常的,就会再回去问一些计算机基础,结合专业成绩考察,若是计算机基础还不错,从第四点综合能力判断值不值得培养,若是面试人数不少的话会放到备考虑,通常会放到经过(看我人多好~)

若是计算机基础,前端基础都挺通常,那确定是不经过了。

最纠结的是评判备考虑,某些点好某些点又很差的难以抉择,因此但愿候选人不要有“突出”的短板,为本身也为面试官。

 

3、面试官是怎么记录面试过程的

面试过程只有十几分钟,面试官在和候选人沟通的同时须要记录相关的关键词,用以佐证面试结果。

咱们这里面试记录有候选人阐述和面试官评价两个部分,下面就列一下我某条“经过”的记录,

候选人阐述

在校期间成绩还能够,奖学金,大赛获奖

大三开始学前端,看视频,看书,在本身博客总结记录

JS比CSS好一些

实习前本身作了三个项目

去stackoverflow,github,官方文档解决问题

规划:先深刻基础,后面会作一些NodeJS相关的,走入全栈

面试官评价

osi七层模型,http/s区别,http四次挥手

进程和线程区别 不了解

前端优化方法 ok   前端安全 通常

语义化 ok

url -> 页面渲染过程 中等(dns查询,网页渲染流程)

垂直居中,使用position, flex布局

js闭包,继承 ok    原生js操做dom 通常

看过jq源码 只知道无new式对象的实现

session和cookie区别

react比jq优势,虚拟dom,setState,组件间通讯(props回调,发布订阅)中等

二分查找 熟悉

 

反应较快,沟通顺畅,话稍多

 

技术基础:中等

前端基础:中等

综合:中等

 

这个“经过”的关键词有点多,有时也不会列举辣么多。

经过的时候会着重列举好的地方,不经过的时候通常多为很差的

 

 

虽然说一天以内面了那么多人,也只能说是面试菜菜,还须要多多改进练习,参与主宰一我的的工做机会,这种感受很特别呀~

 

但愿各位前端儿,可以尽快巩固好本身的基础,包括计算机基础和前端基础。

其一,它是敲门砖;其二,工做以后会懒得去学,也没那么多时间去学基础了。

 

 

 

NPOI 教程 - 3.2 打印相关设置

 

打印设置主要包括方向设置、缩放、纸张设置、页边距等。NPOI 1.2支持大部分打印属性,可以让你轻松知足客户的打印须要。

 

首先是方向设置,Excel支持两种页面方向,即纵向和横向。

image

在NPOI中如何设置呢?你能够经过HSSFSheet.PrintSetup.Landscape来设置,Landscape是布尔类型的,在英语中是横向的意思。若是Landscape等于true,则表示页面方向为横向;不然为纵向。

 

接着是缩放设置,

image

 

这里的缩放比例对应于HSSFSheet.PrintSetup.Scale,而页宽和页高分别对应于 HSSFSheet.PrintSetup.FitWidth和HSSFSheet.PrintSetup.FitHeight。要注意的是,这里的 PrintSetup.Scale应该被设置为0-100之间的值,而不是小数。

 

image

接下来就是纸张设置了,对应于HSSFSheet.PrintSetup.PaperSize,但这里的PaperSize并非随便设置的,而是由一些固定的值决定的,具体的值与对应的纸张以下表所示:

纸张
1 US Letter 8 1/2 x 11 in
2 US Letter Small 8 1/2 x 11 in
3 US Tabloid 11 x 17 in
4 US Ledger 17 x 11 in
5 US Legal 8 1/2 x 14 in
6 US Statement 5 1/2 x 8 1/2 in
7 US Executive 7 1/4 x 10 1/2 in
8 A3 297 x 420 mm
9 A4 210 x 297 mm
10 A4 Small 210 x 297 mm
11 A5 148 x 210 mm
12 B4 (JIS) 250 x 354
13 B5 (JIS) 182 x 257 mm
14 Folio 8 1/2 x 13 in
15 Quarto 215 x 275 mm
16 10 x 14 in
17 11 x 17 in
18 US Note 8 1/2 x 11 in
19 US Envelope #9 3 7/8 x 8 7/8
20 US Envelope #10 4 1/8 x 9 1/2
21 US Envelope #11 4 1/2 x 10 3/8
22 US Envelope #12 4 \276 x 11
23 US Envelope #14 5 x 11 1/2
24 C size sheet
25 D size sheet
26 E size sheet
27 Envelope DL 110 x 220mm
28 Envelope C5 162 x 229 mm
29 Envelope C3 324 x 458 mm
30 Envelope C4 229 x 324 mm
31 Envelope C6 114 x 162 mm
32 Envelope C65 114 x 229 mm
33 Envelope B4 250 x 353 mm
34 Envelope B5 176 x 250 mm
35 Envelope B6 176 x 125 mm
36 Envelope 110 x 230 mm
37 US Envelope Monarch 3.875 x 7.5 in
38 6 3/4 US Envelope 3 5/8 x 6 1/2 in
39 US Std Fanfold 14 7/8 x 11 in
40 German Std Fanfold 8 1/2 x 12 in
41 German Legal Fanfold 8 1/2 x 13 in
42 B4 (ISO) 250 x 353 mm
43 Japanese Postcard 100 x 148 mm
44 9 x 11 in
45 10 x 11 in
46 15 x 11 in
47 Envelope Invite 220 x 220 mm
48 RESERVED--DO NOT USE
49 RESERVED--DO NOT USE
50 US Letter Extra 9 \275 x 12 in
51 US Legal Extra 9 \275 x 15 in
52 US Tabloid Extra 11.69 x 18 in
53 A4 Extra 9.27 x 12.69 in
54 Letter Transverse 8 \275 x 11 in
55 A4 Transverse 210 x 297 mm
56 Letter Extra Transverse 9\275 x 12 in
57 SuperA/SuperA/A4 227 x 356 mm
58 SuperB/SuperB/A3 305 x 487 mm
59 US Letter Plus 8.5 x 12.69 in
60 A4 Plus 210 x 330 mm
61 A5 Transverse 148 x 210 mm
62 B5 (JIS) Transverse 182 x 257 mm
63 A3 Extra 322 x 445 mm
64 A5 Extra 174 x 235 mm
65 B5 (ISO) Extra 201 x 276 mm
66 A2 420 x 594 mm
67 A3 Transverse 297 x 420 mm
68 A3 Extra Transverse 322 x 445 mm
69 Japanese Double Postcard 200 x 148 mm
70 A6 105 x 148 mm
71 Japanese Envelope Kaku #2
72 Japanese Envelope Kaku #3
73 Japanese Envelope Chou #3
74 Japanese Envelope Chou #4
75 Letter Rotated 11 x 8 1/2 11 in
76 A3 Rotated 420 x 297 mm
77 A4 Rotated 297 x 210 mm
78 A5 Rotated 210 x 148 mm
79 B4 (JIS) Rotated 364 x 257 mm
80 B5 (JIS) Rotated 257 x 182 mm
81 Japanese Postcard Rotated 148 x 100 mm
82 Double Japanese Postcard Rotated 148 x 200 mm
83 A6 Rotated 148 x 105 mm
84 Japanese Envelope Kaku #2 Rotated
85 Japanese Envelope Kaku #3 Rotated
86 Japanese Envelope Chou #3 Rotated
87 Japanese Envelope Chou #4 Rotated
88 B6 (JIS) 128 x 182 mm
89 B6 (JIS) Rotated 182 x 128 mm
90 12 x 11 in
91 Japanese Envelope You #4
92 Japanese Envelope You #4 Rotated
93 PRC 16K 146 x 215 mm
94 PRC 32K 97 x 151 mm
95 PRC 32K(Big) 97 x 151 mm
96 PRC Envelope #1 102 x 165 mm
97 PRC Envelope #2 102 x 176 mm
98 PRC Envelope #3 125 x 176 mm
99 PRC Envelope #4 110 x 208 mm
100 PRC Envelope #5 110 x 220 mm
101 PRC Envelope #6 120 x 230 mm
102 PRC Envelope #7 160 x 230 mm
103 PRC Envelope #8 120 x 309 mm
104 PRC Envelope #9 229 x 324 mm
105 PRC Envelope #10 324 x 458 mm
106 PRC 16K Rotated
107 PRC 32K Rotated
108 PRC 32K(Big) Rotated
109 PRC Envelope #1 Rotated 165 x 102 mm
110 PRC Envelope #2 Rotated 176 x 102 mm
111 PRC Envelope #3 Rotated 176 x 125 mm
112 PRC Envelope #4 Rotated 208 x 110 mm
113 PRC Envelope #5 Rotated 220 x 110 mm
114 PRC Envelope #6 Rotated 230 x 120 mm
115 PRC Envelope #7 Rotated 230 x 160 mm
116 PRC Envelope #8 Rotated 309 x 120 mm
117 PRC Envelope #9 Rotated 324 x 229 mm
118 PRC Envelope #10 Rotated 458 x 324 mm

(此表摘自《Excel Binary File Format (.xls) Structure Specification.pdf》)

HSSFSheet下面定义了一些xxxx_PAPERSIZE的常量,但都是很是经常使用的纸张大小,若是知足不了你的须要,能够根据上表本身给PaperSize属性赋值。因此,若是你要设置纸张大小能够用这样的代码:

HSSFSheet.PrintSetup.PaperSize=HSSFSheet.A4_PAPERSIZE;

HSSFSheet.PrintSetup.PaperSize=9; (A4 210*297mm)

 

image

再下来就是打印的起始页码,它对应于HSSFSheet.PrintSetup.PageStart和 HSSFSheet.PrintSetup.UsePage,若是UsePage=false,那么就至关于“自动”,这时PageStart不起做用; 若是UsePage=true,PageStart才会起做用。因此在设置PageStart以前,必须先把UsePage设置为true。

 

image

“打印”栏中的“网格线”设置对应于HSSFSheet.IsPrintGridlines,请注意,这里不是 HSSFSheet.PrintSetup下面,因此别搞混了。这里之因此不隶属于PrintSetup是由底层存储该信息的record决定的,底层是 把IsGridsPrinted放在GridsetRecord里面的,而不是PrintSetupRecord里面的,尽管界面上是放在一块儿的。另外还 有一个HSSFSheet.IsGridsPrinted属性,这个属性对应于底层的gridset Record,但这个record是保留的,从微软的文档显示没有任何意义,因此这个属性请不要去设置。

“单色打印”则对应于HSSFSheet.PrintSetup.NoColors,这是布尔类型的,值为true时,表示单色打印。

“草稿品质”对应于HSSFSheet.PrintSetup.IsDraft,也是布尔类型的,值为true时,表示用草稿品质打印。

这里的打印顺序是由HSSFSheet.PrintSetup.LeftToRight决定的,它是布尔类型的,当为true时,则表示“先行后列”;若是是false,则表示“先列后行”。

 

在NPOI 1.2中,“行号列标”、“批注”和“错误单元格打印为”、“页边距”暂不支持,将在之后的版本中支持。

 

 

 

前端XSS相关整理

 

前端安全方面,主要须要关注 XSS(跨站脚本攻击 Cross-site scripting) 和 CSRF(跨站请求伪造 Cross-site request forgery)

固然了,也不是说要忽略其余安全问题:后端范畴、DNS劫持、HTTP劫持、加密解密、钓鱼等

CSRF主要是借用已登陆用户之手发起“正常”的请求,防范措施主要就是对须要设置为Post的请求,判断Referer以及token的一致性,本文不展开

相对来讲,XSS的内容就很是庞大了,下面就来整理一下一些XSS的知识点。比较匆忙,可能有点乱哈~

 

1、XSS

恶意攻击者向页面中注入可执行的JS代码来实现XSS的攻击。

如常见的

Payload:<script>alert(1)</script>
<div>[输出]</div>
 
<div><script>alert(1)</script></div>

这个 Payload 能够从编辑区域而来

<input type="text" value="[输入]" />

固然,输入和输出的位置还能够出如今其余地方,根据输入输位置的不一样,能够造成不一样类型的XSS,相应的防范措施也不一样。

 

1.1 XSS的分类

通常来讲,能够将XSS分为三类:反射型XSS、存储型XSS、DOM-base 型XSS

1.1.1 反射型XSS

大多经过URL进行传播,发请求时,XSS代码出如今URL中,提交给服务端。服务端未进行处理或处理不当,返回的内容中也带上了这段XSS代码,最后浏览器执行XSS代码

好比在 php的smarty模板中直接获取url的参数值

Payload: <script>alert(1)</script>
http://local.abc.com/main/?r=abc/index&param=<script>alert(1)</script>
 
<div><{$smarty.get.param}></div>

X-XSS-Protection

新版Chrome和Safari中,已自动屏蔽了这种XSS,形如

这个屏蔽是由 XSS Auditor操做的,它由HTTP返回头部进行控制,有四个可选值

X-XSS-Protection : 0    关闭浏览器的XSS防御机制
X-XSS-Protection : 1    删除检测到的恶意代码(若是不指定,IE将默认使用这个)
X-XSS-Protection : 1; mode=block   若是检测到恶意代码,将不渲染页面 (若是不指定,Chrome将默认使用这个)
X-XSS-Protection : 1; report=<reporting-uri> 删除检测到的恶意代码,并经过report-uri发出一个警告。

前三个在IE和Chrome中有效,最后一个只在Chrome中有效

能够手动在设置请求头看看变化

header('X-XSS-Protection: 1; mode=block');

建议配置为后两个的结合,禁止页面渲染并进行上报

header('X-XSS-Protection: 1; mode=block; report=www.xss.report');

不建议仅仅配置为1,由于它删除恶意代码的功能有时比较鸡肋,可能会弄巧成拙。

另外,这个配置只能充当辅助做用,不能彻底依赖,其也可能会产生一些问题

 

不过在Firefox中并未屏蔽

在IE中的XSS Filter也默认也开启了屏蔽,也可手动关闭试试,或者经过HTTP头部进行控制

 

1.1.2 存储型XSS

提交的XSS代码会存储在服务器端,服务端未进行处理或处理不当,每一个人访问相应页面的时候,将会执行XSS代码

如本文开始的第一个例子

1.1.3 DOM-base 型XSS

这个类型和反射型的有点相似,区别是它不须要服务端参与

好比在JS中直接获取URL中的值

复制代码
Payload: alert('xss')
http://local.abc.com/main/?r=abc/index#alert('xss')
 
<script>
    var hash = eval(location.hash.slice(1));
</script>
复制代码

 

 

另外,有些攻击方式的类型是单一的,有些是混合的。防范攻击,不该仅根据类型来防范,而应根据输入输出的不一样来应对。

在反射型和DOM-base型中,通常会经过设置一些有诱导性质的连接,用户点击连接后则触发连接中的XSS

Content Security Policy(CSP)内容安全策略

为了防范XSS,CSP出现了。

CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源能够加载和执行,提供了这种白名单以后,实现和执行则由浏览器完成

经过一系列的自定义配置,能够在很大程度上防止恶意脚本的攻击,建议进行配置。

不过策略比较新,在各浏览器也有一些兼容性的问题。另外,彷佛仍是能够经过一些手段绕过的,这里就不展开了

Cookie 配置

大多使用cookie来实现对用户的认证。若是攻击者拿到了这个认证cookie,就能够登陆了用户的帐号了

XSS的主要目的是为了获得cookie,固然也不只是为了获取cookie

cookie安全注意点

Httponly:防止cookie被xss偷

https:防止cookie在网络中被偷

Secure:阻止cookie在非https下传输,不少全站https时会漏掉

Path :区分cookie的标识,安全上做用不大,和浏览器同源冲突

经过设置 cookie的几个属性,能够在必定程度上保障网站的安全

不过并无十全十美的东西,虽然攻击门槛提升了,但HttpOnly在某些特定状况下仍是能绕过的,道高一尺魔高一点一尺呀

 

1.2 执行JS代码

XSS的目的通常是盗取cookie,通常须要经过JS 的 document.cookie来获取这个值。

因此要先思考的是:在什么地方能够执行JS相关的代码

而后要思考的是:攻击者能不能在这些地方构造出可以执行的脚本

1.2.1  <script>标签中

<script>alert(1);</script>

1.2.2 HTML中的某些事件

<img src="1" onerror="alert(1)" >
 
<input type="text" onfocus="alert(1)">
 
<span onmouseover="alert(1)"></span>

1.2.3  javascript: 伪协议

<a href="javascript:alert(1)">test</a>
<iframe src="javascript:alert(1)"></iframe>
 
 
location.href = 'javascript:alert(1)'

对于事件的执行触发,是有机会防护的,围观 这篇文章

1.2.4  base64编码的  data: 伪协议

Payload: <script>alert('XSS')</script> ,它的base64编码为PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">test</a>

1.2.5  css中的expression表达式

仅在IE8如下才支持expression,能够忽略这个了

<span style="color:1;zoom:expression(alert(1));"></span>

1.2.6 css中的src

不少文章都说到这个payload,然鹅并无生效,不知真假

根据一些讨论,在css中是很难实现xss的

.abc {
    background: url(...)
} 

1.2.7 使用 eval、new Function、setTimeout 执行字符串时

复制代码
setTimeout('alert(1)');
 
eval('alert(2)');
 
var f = new Function('alert(3)');
f();
复制代码

 

 

1.3 编码与解码

防范XSS,比较通用的作法是:提交保存前对特殊字符进行过滤转义,进行HTML实体的编码

复制代码
var escape = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#x27;',
    '`': '&#x60;'
};
复制代码

事实上,仅仅这样作仍是不够的

那为何要进行HTML实体的编码呢?

这涉及到浏览器的解析过程。

浏览器在解析HTML文档期间,根据文档中的内容,会通过 HTML解析、JS解析和URL解析几个过程

 

首先浏览器接收到一个HTML文档时,会触发HTML解析器对HTML文档进行词法解析,这完成HTML解码工做并建立DOM树。

若是HTML文档中存在JS的上下文环境,JavaScript解析器会介入对内联脚本进行解析,完成JS的解码工做。

若是浏览器遇到须要URL的上下文环境,URL解析器也会介入完成URL的解码工做。

 URL解析器的解码顺序会根据URL所在位置不一样,可能在JavaScript解析器以前或以后解析

1.3.1 HTML实体编码

浏览器会对一些字符进行特殊识别处理,好比将 < > 识别为标签的开始结束。

要想在HTML页面中呈现出特殊字符,就须要用到对应的字符实体。好比在HTML解析过程当中,若是要求输出值为 < > ,那么输入值应该为其对应的实体 &lt; &gt;

 

字符实体以&开头 + 预先定义的实体名称,以分号结束,如“<”的实体名称为&lt; 

或以&开头 + #符号 以及字符的十进制数字,如”<”的实体编号为&#60;

或以&开头 + #x符号 以及字符的十六进制数字,如”<”的实体编号为&#x3c;

字符都是有实体编号的但有些字符没有实体名称。

 

普通编码与实体编码的在线转换

1.3.2 Javascript编码

Unicode 是字符集,而 utf-8,utf-16,utf-32 是编码规则

最经常使用的如“\uXXXX”这种写法为Unicode转义序列,表示一个字符,其中xxxx表示一个16进制数字

如”<” Unicode编码为“\u003c”,不区分大小写

普通编码与Unicode转义序列的在线转换

Unicode字符集大全

1.3.3 URL编码

%加字符的ASCII编码对于的2位16进制数字,如”/”对应的URL编码为%2f

转换可使用 JS 自带的 encodeURIComponent 和 decodeURLComponent 方法来对特殊字符进行转义,也能够对照ASCII表为每一个字符进行转换

1.3.4 编码解码分析

<span class="a<b">abc</span>
等价于
<span class="a&lt;b">abc</span>

上述代码中

编码顺序:HTML编码

解码顺序:HTML解码

 

<a href="//www.baidu.com?a=1&b=2">abc</a>
等价于
<a href="//www.baidu.com?a=1%26b=2">abc</a>
等价于
<a href="//www.baidu.com?a=1&#37;&#50;&#54;b=2">abc</a>

上述代码中

编码顺序:URL编码 -> HTML编码

解码顺序:HTML解码 -> URL解码

 

复制代码
<a href="#" onclick="alert(1)">abc</a>
等价于
<a href="#" onclick="\u0061\u006c\u0065\u0072\u0074(1)">abc</a>
等价于
<a href="#" onclick="&#92;&#117;&#48;&#48;&#54;&#49;&#92;&#117;&#48;&#48;&#54;&#99;&#92;&#117;&#48;&#48;&#54;&#53;&#92;&#117;&#48;&#48;&#55;&#50;&#92;&#117;&#48;&#48;&#55;&#52;&#40;&#49;&#41;">abc</a>
复制代码

上述代码中

编码顺序:Javascript编码 -> HTML编码

解码顺序:HTML解码 -> Javascript解码

须要注意的是,在JS的解码中,相关的标识符才能被正确解析(如这里的 alert 标识符),

像圆括号、双引号、单引号等等这些控制字符,在进行JavaScript解析的时候仅会被解码为对应的字符串文本(好比这里并未对 (1) 进行编码,若是对括号及括号里面内容作JS编码,将没法执行alert函数 )

 

复制代码
<a href="javascript:alert(1<2)">abc</a>
等价于
<a href="javascript:\u0061\u006c\u0065\u0072\u0074(1<2)">abc</a>
等价于(使用JS的方法进行的URL编码)
<a href="javascript:alert(1%3C2)">abc</a>
等价于(使用转换成对应ASCII编码对应2位16进制数字的URL编码)
<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34%28%31%3C%32%29">abc</a>
等价于
<a href="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#37;&#51;&#67;&#50;&#41;">abc</a>
复制代码

上述代码中

编码顺序:Javascript编码 -> URL编码 -> HTML编码

解码顺序:HTML解码 -> URL解码 -> Javascript解码

这里还须要注意的是,在URL的编码中,不能对协议类型(这里的 javascript: )进行编码,不然URL解析器会认为它无类型,致使没法正确识别

 

应用这个解析顺序,看如下这个例子

输入源 abc为URL中的值,若是后端仅进行了HTML的编码,仍是有问题的

Payload-0: http://local.abc.com/main/?r=abc/index&abc=');alert('11
<span onclick="test('<{$abc}>')">test</span>
 
<span onclick="test('&#x27;);alert(&#x27;11')">test</span>

解码顺序先是进行HTML解码,此时会将 &#x27解析成 ' 号,接着进行Javascript的解码,识别到 ' 便可闭合test函数,调用成功

因此,这种状况下,后端须要先进行Javascript编码再进行HTML的编码

 

固然,还有其余顺序的混合。也须要考虑编码工做能不能正确地进行过滤

<a href="javascript:window.open('[输入源]')">

解码顺序:

HTML解码 -> URL解码 -> Javascript解码 -> URL解码

 

引伸出去,还有一些字符集的知识点,脑袋疼,就不在这整理了

 

1.4 常见XSS攻击方式

XSS的攻击脚本多种多样,在使用了模板(前端模板和后端模板)以后,须要格外注意数据的输入输出

下面列举几个常见的

 

1.4.1 PHP使用Yii框架中的Smarty模板

有时候会使用 $smarty.get.abc 获取URL中的参数,未经转义

复制代码
Payload-1: http://local.abc.com/main/?r=abc/index&abc=<script>alert(1)</script>
<span><{$smarty.get.abc}></span>
 
<span><script>alert(1)</script></span>
 
 
Payload-2: http://local.abc.com/main/?r=abc/index&abc="><script>alert(1)</script>
<a href="/main/?param=<{$smarty.get.abc}>">abc</a>
 
<a href="/main/?param="><script>alert(1)</script>">abc</a>
 
 
Payload-3: http://local.abc.com/main/?r=abc/index&abc=" onmouseover=alert(1)
<a href="/main/?param=<{$smarty.get.abc}>">abc</a>
 
<a href="/main/?param=" onmouseover="alert(1)" ">abc</a>
 
 
Payload-4: http://local.abc.com/main/?r=abc/index&urlTo=javascript:alert(1)
<a href="<{$smarty.get.urlTo}>">urlTo</a>
 
<a href="javascript:alert(1)">urlTo</a>
 
 
Payload-5: http://local.abc.com/main/?r=abc/index&urlTo=data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pgo=
<a href="<{$smarty.get.urlTo}>">urlTo</a>
 
<!-- 对 <script>alert(1)</script> 进行 base64编码 为 PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pgo= -->
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pgo=">urlTo</a>
 
 
Payload-6: http://local.abc.com/main/?r=abc/index&abc=</script><script>alert(1)//
<script>
    var abc = '<{$smarty.get.abc}>';
</script>
 
<script>
    // 第一个 script标签被闭合,虽然会报错,但不会影响第二个script标签,注意须要闭合后面的引号或注释,防止报错
    var abc = '</script><script>alert(1)//';
</script>
 
 
Payload-7: http://local.abc.com/main/?r=abc/index&abc=alert(1)
<script>
    if (<{$smarty.get.abc}> == 'abc') {
        console.log(1);
    }
</script>
 
<script>
    // 此处由于没有用引号,因此能够直接执行 alert(1)
    if (alert(1) == 'abc') {
        console.log(1);
    }
</script>
 
 
Payload-8: http://local.abc.com/main/?r=abc/index&abc='){}if(alert(1)){//
<script>
    if ('<{$smarty.get.abc}>' == 'abc') {
        console.log(1);
    }
</script>
 
 
<script>
    // 用了引号以后,闭合难度增长,不过仍是能够闭合起来的
    if (''){}if(alert(1)){//' == 'abc') {
        console.log(1);
    }
</script>
 
 
Payload-9: http://local.abc.com/main/?r=abc/index&abc=');alert('1
Payload-10: http://local.abc.com/main/?r=abc/index&abc=%26%2339%3B);alert(%26%2339%3B1    对参数进行了HTML的实体编码
<span onclick="test('<{$smarty.get.abc}>')">test</span>
 
<span onclick="test('');alert('1')">test</span>
 
 
Payload-11: http://local.abc.com/main/?r=abc/index&abc=" onfocus="alert(1)" autofocus="autofocus"
<input type="text" id="input" value="<{$smarty.get.abc}>">
 
<input id="input" value="" onfocus="alert(1)" autofocus="autofocus" "="" type="text">
复制代码

在线 base64编码解码

解决方式为:

不使用 $smarty.get 相关获取参数,改用后端过滤数据后再返回参数;

Yii框架中相应位置配置:'escape_html' => true

在页面标签内嵌的脚本中直接使用后端返回的数据并不安全,后端可能过滤不完善(见Payload-7和Payload-0)避免直接使用

能够改用将数据存储在属性中,再经过脚本获取属性的方式

 

1.4.2 JS操做DOM的时候是否会有XSS隐患?

使用 jQuery的append相关方法时(好比 html方法)可能会

复制代码
// 执行
$($0).html('<script>alert(1);</script>');
 
// 执行
$($0).html('\u003cscript\u003ealert(1);\u003c/script\u003e');
 
// 执行
$($0).append('<script>alert(1);</script>');
 
// 不执行
$0.innerHTML = '<script>alert(1);</script>';
复制代码

缘由是在jQuery中使用了eval方法执行相应的脚本,须要注意的是,Unicode编码的字符在运算中会被解析出来

因此,要注意的是

使用jQuery设置DOM内容时,记得先对内容进行转义

 

对于设置输入框的值,是安全的

复制代码
<input type="text" id="input">
<textarea value="12" id="textarea"></textarea>
 
<script>
    // 不执行
    document.getElementById('input').value = '"><script>alert(1);<\/script>';
    document.getElementById('textarea').value = '"><script>alert(1);<\/script>';
     
    // 不执行
    $('#input').val('" onmouseover="alert(1)"');
    $('#textarea').val('" onmouseover="alert(1)"');
</script>
复制代码

对于设置属性的值,是安全的

复制代码
<input type="text" id="input">
<textarea value="12" id="textarea"></textarea>
 
<script>
    // 不执行
    document.getElementById('input').setAttribute('abc', '"><script>alert(1);<\/script>');
    document.getElementById('textarea').setAttribute('abc', '"><script>alert(1);<\/script>');
 
    // 不执行
    $('#input').attr('abc', '" onmouseover="alert(1)"');
    $('#textarea').attr('abc', '" onmouseover="alert(1)"');
</script>
复制代码

1.4.3 前端Handlebars模板中的安全问题

后端有Smarty模板,前端也能够有Handlebars模板,使用模板有利于开发维护代码。不过和后端同样,使用模板也要考虑到XSS的问题

Handlebars模板中可选择是否开启转义

复制代码
<!-- 转义,若是name的值已经被后端转义为实体符&gt; 那么Handlebars将会转换成 &amp;gt; 在浏览器中将会显示 &gt; -->
<!-- 因此此时须要先将 &gt; 转回 > 再传入Handlebars模板,才能看到正确的 > 符号 -->
<span>{{name}}</span>
 
<!-- 不转义 -->
<span>{{{name}}}</span>
复制代码

因此要注意的第一点是:

若是使用了转义占位符,就须要先进行还原;若是不使用转义,就不要还原,不然将形成XSS

另外,Handlebars模板能够自定义helper,helper有两种使用方式,直接返回数据或返回子层

复制代码
<!-- 模板 [A] -->
<script type="text/template" id="test-tpl">
    <span abc="{{#abc attrData}}{{/abc}}">111{{#abc data}}{{/abc}}</span>
    <span>
        <input type="text" value="{{#abc attrData}}{{/abc}}">
    </span>
</script>
 
<!-- 模板 [B] -->
<!-- <script type="text/template" id="test-tpl">
    <span abc="{{#abc attrData}}{{attrData}}{{/abc}}">111{{#abc data}}{{data}}{{/abc}}</span>
    <span>
        <input type="text" value="{{#abc attrData}}{{attrData}}{{/abc}}">
    </span>
</script> -->
 
 
<!-- 容器 -->
<span id="test"></span>
 
<script src="........./handlebars/handlebars-v4.0.5.js"></script>
 
<script type="text/javascript">
    // 自定义helper
    Handlebars.registerHelper('abc', function (text, options) {
        // 对输入数据进行过滤 [1]
        // text = Handlebars.Utils.escapeExpression(text)
 
        // helper直接返回数据 [2]
        return text;
 
        // helper返回子层 [3]
        // return options.fn(this);
    });
 
    // Handlebars获取数据
    function getHtml(html, data) {
        let source = Handlebars.compile(html);
        let content = source(data);
        return content;
    }
 
    var data = '<script>alert(1);<\/script>';
    var attrData = '" onmouseover="alert(2)"';
 
    // 渲染
    $('#test').html(getHtml($('#test-tpl').html(), {
        data: data,
        attrData: attrData
    }));
</script>
复制代码

进入页面后,将会执行 alert(1) ,而后鼠标滑过span或input元素,将会执行 alert(2)

这是由于Handlebars在处理helper时,若是是返回数据,将不进行转义过滤

解决方案为:

若是使用了自定义的helper直接返回数据,先转义一遍,即取消注释[1] 处 代码

或者不直接返回数据,即注释模板[A],[1] 和[2]处,取消注释模板[B],[3]处 代码

 

另外,前端模板会频繁和JS进行交互,在前端直接使用JS获取URL参数并放到模板中时,要格外注意防止产生DOM-base型XSS,以下面这段代码

复制代码
Payload: http://local.abc.com/main/?r=abc/index&param=%22%20onmouseover=%22alert(2)%22
 
function getUrlParam(name) {
    let value = window.location.search.match(new RegExp('[?&]' + name + '=([^&]*)(&?)', 'i'));
    return value ? decodeURIComponent(value[1]) : '';
}
var attrData = getUrlParam('param');
复制代码

1.4.4  React JSX模板中的 dangerouslySetInnerHTML

<span dangerouslySetInnerHTML={{__html: '<script>alert(1);</script>'}}></div>

这段代码会执行么

事实上,并不会。与模板不一样,它使用的是 innerHTML来更新DOM元素的内容,因此不会执行恶意代码

不过,这个内容不会显示在页面中,若是这时正常的一段内容,就应该转义以后再放入 __html的值中

 

1.4.5 在React的服务端渲染中,也要注意安全问题

服务端渲染须要一个初始的state,并与客户端作对应

可能会长这样子

复制代码
<!-- 客户端 -->
<div id="content">
    <|- appHtml |>
</div>
<script id="preload-state">
    var PRELOAD_STATE = <|- preloadState |>
</script>
 
 
// 服务端
res.render('xxx.html', {
    appHtml: appHtml,
    preloadState: JSON.stringify(preloadState).replace(/</g, '\\u003c')
});
复制代码

相似模板,服务端将数据传给客户端时,在模板组装数据的时候要防止构造出闭合 <script>标签的情景

这里能够将 < 替换成对应的Unicode字符串,在JS中获取该字符串时,能够直接识别为 <

 

1.4.6 百度编辑器的编辑源码,可能会有安全问题

在编辑器内直接输入这串内容,不会执行。点击查看源码,能够看到已经通过转义

 

咱们能够直接在这里修改源码

 

再切换回去,一个XSS漏洞就产生了,若是稍加不注意就会被利用。

因此,在前端范畴必须将此入口去除,后端也应增强一些特殊字符的转义

 

1.4.7 谨防 javascript: 伪协议

连接中带有 javascript: 伪协议可执行对应的脚本,常见于 a 的 href 标签和 iframe的 src 中

<a href="javascript:alert(1)">test</a>
<!-- 冒号: 的HTML实体符 -->
<a href="javascript&#58;alert(1)">test</a>
<iframe src="javascript:alert(1)"></iframe>

输入源多为一个完整的URL路径,输出地方多为模板与JS的操做

<a href="<{$urlTo}>">test</a>
<a href="{{{urlTo}}}">test</a>
 
location.href = getUrlParam('urlTo');

普通的HTML实体符并不能过滤这个伪协议

须要知道的是,javascript: 可以正常工做的前提为:开始URL解析时没有通过编码

解决方案:

1. 前端后端都要先对 '"><& 这些特殊字符进行过滤转义,特别是在与模板共用时,它们颇有可能会闭合以产生攻击,或者利用浏览器解码的顺序来绕过不严格的过滤

2.严格要求输入的URL以 https:// 或 http:// 协议开头

3.严格限制白名单协议虽然可取,但有时会形成限制过头的问题。还能够单独限制伪协议,直接对 javascript: 进行过滤

过滤时须要兼容多层级的嵌套: javajavajavascript:script:script:alert(1) 

同时显示的时候,将多余的冒号 : 转义成URL编码,注意避免把正常的协议头也转义了,要兼容正常的URL

转义冒号要使用 encodeURIComponent , encodeURI转义不了,另外escape也不建议使用,关于三者的区别

复制代码
function replaceJavascriptScheme(str) {
    if (!str) {
        return '';
    }
    return str.replace(/:/g, encodeURIComponent(':'));
}
 
Handlebars.registerHelper('generateURL', function (url) {
    url = Handlebars.Utils.escapeExpression(url);
 
    if (!url) {
        return '';
    }
 
    var schemes = ['//', 'http://', 'https://'];
    var schemeMatch = false;
 
    schemes.forEach(function(scheme) {
        if (url.slice(0, scheme.length) === scheme) {
            url = scheme + replaceJavascriptScheme(url.slice(scheme.length));
            schemeMatch = true;
            return false;
        }
    });
 
    return schemeMatch ? url : '//' + replaceJavascriptScheme(url);;
});
复制代码

1.4.8  注意符号的闭合  '"><  和其余特殊符号

闭合标签,闭合属性是很常见的一种攻击方式,要重点关注哪里可能被恶意代码闭合。

本文使用了模板Smarty,在使用模板的时候,通常都将模板变量放在了引号中,须要带符号来闭合来实现攻击

<span abc="<{$abc}>"></span>
" onclick=alert(1)

在设置了特殊符号转义的状况下,这种攻击方式将失效

然鹅当输出的数据不在引号当中时,防范难度将加大。由于分离属性可使用不少符号,黑名单过滤可能列举不全

abc/index?abc=1 onclick=alert(1)
 
<span id="test1" abc=<{$abc}>>test</span>

因此,尽可能用引号包裹起变量

另外,也要避免在 <script>标签中直接使用模板中的变量,能够改用将模板变量缓存在HTML属性中,JS再进行取值

防止该 <script>标签被恶意代码闭合,而后执行恶意代码,例子可见上文的 Payload-6

还要注意JS的语法,在某些时候,特殊符号 反斜杠\ 没有过滤的话,也有安全问题

复制代码
<script>
    var aaaa = '?a=<{$a}>' + '&b=<{$b}>';
</script>
 
?r=abc/index&a=\&b==alert(1);function b(){}//
 
 
<script>
    // 构造处可执行的代码,若是空格也被转义了,还能够用注释占位 function/**/b(){}
    var aaaa = '?a=\' + '&b==alert(1);function b(){}//';
</script>
复制代码

假设只对 ' " > < & 进行了转义,能够试试从URL拿数据,这里须要利用到JS代码中关键的 & 符号与 \ 转义符

\ 将第一个分号转义为字符串

& 与运算将先后分离

b的参数加上 = 号构造处bool运算

为了防止b未定义,在后面用函数提高特性来定义

最后注释符防止报错

为了攻击也是蛮拼的....因此最好仍是要对JS操做的字符用反斜杠进行转义一下,好比 \  -> \\

 

1.4.9 图片 exif 信息含有恶意代码

另外一种XSS攻击的方式是在图片的exif信息中注入脚本,在读取图片信息时要注意过滤

在早期的不少插件中都没有进行处理,如以前爆出的 Chrome Exif Viewer 插件问题,可能还有相关插件没有这些意识,平时也要注意

另外,站点自身在读取文件信息时也要注意,攻击者在上传文件前,可能会对文件的信息进行修改,过滤不当极可能就形成严重的存储型漏洞

 

 

 

委托入门案例

 

我本人对于委托最多的使用就是子线程调用主线程的控件的使用。可能使用winform或者wpf的人接触的多一点。

这里最主要仍是给你们看看委托的案例吧

delegate void showMsg(string Msg);
showMsg s;

第一种委托的方法
s+=func;
s("aaa");


第二种委托方法(这种方式用的多)
s=new showMsg(func);
s("aaa")'

public void func(string s)
{
console.WriteLine("aaa"+s);
}

 

固然也有 这种方式的委托,在应用程序的主线程上执行指定的委托

this.Invoke(new Action(()=>{Console.WriterLine("aaa")}); 

  异步委托
this.Dispatcher.BeginInvoke((Action)delegate ()
                {Console.WriterLine("aaa")});
相关文章
相关标签/搜索