你所不知道的 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")});
相關文章
相關標籤/搜索