0%

一直都有聽過XSS攻擊的原理跟方式,但都沒有好好認真研究過,剛好最近看到一個小遊戲在這邊推薦給大家:
瞭解XSS攻擊的小遊戲

查了一下.NET防止XSS攻擊的有效方法,剛好保哥有寫過相關的文章
保哥-推薦使用 Microsoft Anti-Cross Site Scripting Library v3.1
裡面介紹的非常詳細,這邊就不再多做贅述了。

唯一需要特別注意的地方是Anti-XSS Library在4.2版的時候將GetSafeHtml 、GetSafeHtmlFragment移到了新的DLL了。所以如果依照文章去下載這個DLL會發現沒有這兩個方法可用,請改用Nuget搜尋HtmlSanitizationLibrary

[![](http://4.bp.blogspot.com/-El2JuoTjn70/U42JPHwLqqI/AAAAAAAAEOM/z99tk-Wb_AI/s1600/1.png)](http://4.bp.blogspot.com/-El2JuoTjn70/U42JPHwLqqI/AAAAAAAAEOM/z99tk-Wb_AI/s1600/1.png)

使用方法也變成

1
2
Sanitizer.GetSafeHtmlFragment(inputext);

真是很好很強大阿!!!!

有時候大量資料批次匯入時,我們會用寫SQL語法的方式增加效率(LinqToSql會讓你慢到server timeout),但常常發生SQL處理速度太快,造成datein的時間完全一樣,讓人分不清楚哪筆先哪筆後 這種先後順序在權限的處理上又異常的重要,畢竟權限通常都是拿最後一筆的時間再繼續往下疊加下去,如果分不出哪一筆應該是最後一筆可就慘了阿!!!

SQL表示:今天的我沒有極限

[![](http://3.bp.blogspot.com/-yo13exV70Lw/U4VbOW1w9OI/AAAAAAAAEN8/hulc_I52GBk/s1600/1.png)](http://3.bp.blogspot.com/-yo13exV70Lw/U4VbOW1w9OI/AAAAAAAAEN8/hulc_I52GBk/s1600/1.png)
所以要在每一筆寫入的時候告訴SQL Server說,"來,您辛苦了。休息個0.1秒再繼續吧!!"
這時候你就會需要WAITFOR DELAY語法了([MSDN解說](http://msdn.microsoft.com/zh-tw/library/ms187331.aspx))
```sql --每insert一筆都呼叫一次 WAITFOR DELAY '00:00:00.010'

```
打完收工

需求:將Table_A的資料塞到Table_B,並把Table_B產生的ID編號回寫回Table_A的對應欄位 ```sql
– 宣告變數
DECLARE @para1 VARCHAR(50)
DECLARE @para2 uniqueidentifier
DECLARE @para3 VARCHAR(100)

– 宣告指標變數
DECLARE _cursor CURSOR FOR
SELECT s1,s2,s3 FROM Table_A where eiplstatus = 1

– 啟用指標變數
OPEN _cursor
– 以指標變數為基準點, 將取出的欄位值,依序塞給我們自訂的變數,亦即將每筆s1 => @para1、 s2 => @para2 、s3 => @para3
FETCH NEXT FROM _cursor INTO @para1,@para2,@para3

WHILE @@FETCH_STATUS = 0
BEGIN
insert into Table_B(c1,c2,c3) values(@para1,@para2,@para3)
SET @id = SCOPE_IDENTITY();

update Table_A set id = @id where CURRENT of _cursor

-- 指標變數往下移動, 並將取出的欄位值, 設定給我們自訂的變數
FETCH NEXT FROM _cursor INTO @para1,@para2,@para3

END

– 關閉指標變數
CLOSE _cursor
– 釋放指標變數
DEALLOCATE _cursor


[![](http://4.bp.blogspot.com/-O5EO2Xn1EKo/UqWGOc7xaRI/AAAAAAAAEM0/dPda1T6sNAI/s400/IMG_0440.JPG)](http://4.bp.blogspot.com/-O5EO2Xn1EKo/UqWGOc7xaRI/AAAAAAAAEM0/dPda1T6sNAI/s1600/IMG_0440.JPG) 最近心情持續低氣壓,想在FB上抒發一下心情卻又礙於人多口雜。希望能在這找到屬於自己的另一個僻靜小天地 剛剛看到有人用CSS畫出幾個下雨的樣式,正好也符合自己的心境就來跟部落格整合一下好了。 [下雨CSS請參考](http://www.blogger.com/blogger.g?blogID=6692337573339064262) html
1
2
3
4
<div class="body">
<section class="rain"></section>
</div>

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// number of drops created.
var nbDrop = 858;

// function to generate a random number range.
function randRange( minNum, maxNum) {
return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
}

// function to generate drops
function createRain() {

for( i=1;i < nbDrop;i++) {
var dropLeft = randRange(0,1600);
var dropTop = randRange(-1000,1400);

$('.rain').append('<div class="drop" id="drop'+i+'"></div>');
$('#drop'+i).css('left',dropLeft);
$('#drop'+i).css('top',dropTop);
}

}
// Make it rain
createRain();

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
div.body {
background:#0D343A;
background:-webkit-gradient(linear,0% 0%,0% 100%, from(rgba(13,52,58,1) ), to(#000000) );
background: -moz-linear-gradient(top, rgba(13,52,58,1) 0%, rgba(0,0,0,1) 100%);

overflow:hidden;}

.drop {
background:-webkit-gradient(linear,0% 0%,0% 100%, from(rgba(13,52,58,1) ), to(rgba(255,255,255,0.6)) );
background: -moz-linear-gradient(top, rgba(13,52,58,1) 0%, rgba(255,255,255,.6) 100%);
width:1px;
height:89px;
position: absolute;
bottom:200px;
-webkit-animation: fall .63s linear infinite;
-moz-animation: fall .63s linear infinite;
}

/* animate the drops*/
@-webkit-keyframes fall {
to {margin-top:900px;}
}
@-moz-keyframes fall {
to {margin-top:900px;}
}

[雨滴請參考](http://codepen.io/lbebber/full/uIiJp)

phantomjs如何使用,詳細請參考參考黑暗執行緒前輩的文章

首先寫了一支snapshot.js放到phantomjs的根目錄

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var page = require('webpage').create(),
system = require('system'),
edmid,
address;

address = system.args[1];
edmid = system.args[2];
path = system.args[3];

page.open(address,function(status){

page.render(path + '/' + edmid+'.png');
phantom.exit();
});

這支JS需要傳遞三個參數,1.網址 2.圖片的名稱 3.拍好的圖片存的路徑
在cmd的執行方式如下
這次的功能是要在網站上按下一個按鈕後就對特定的網頁進行快照,程式如下

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
//phantomjs在伺服器上的根目錄資料夾
string path = HostingEnvironment.MapPath(@"~/phantomjs");
//因為拍照可能需要數秒的時間,避免網頁被hand住所以切出執行緒來進行。故抓MapPath的方式需要改成 HostingEnvironment.MapPath
//這裡是我把拍好的圖片放到哪個資料夾的路徑
string snapshotPath = HostingEnvironment.MapPath("~/phantomjs/snapshot");

//透過Process這個類別來對cmd操作
using (System.Diagnostics.Process exep = new System.Diagnostics.Process())
{
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.UseShellExecute = false;
p.Start();

//StandardInput的資訊流指定給StreamWriter ,這樣只要透過StreamWriter寫指令就等於對cmd下command了
StreamWriter sw = p.StandardInput;
sw.WriteLine(@"cd\");
sw.WriteLine(string.Format(@"{0}:", path.Substring(0, 1)));
sw.WriteLine(@"cd " + path);
sw.WriteLine(string.Format(@"phantomjs snapshot.js {0} {1} {2}", 網址, 圖片名稱, snapshotPath ));
sw.Close();
p.WaitForExit();
}

重點在於只要自己透過cmd操作過phantomjs.exe來拍照,依樣畫葫蘆的透過Process逐步的下指令就可以達成了!!

另外phantomjs是將要被拍照的DOM元件抓下來在進行組合拍照,有了這個特性你就可以對想拍照的網站進行一些修改。例如載入JQuery把某個區塊移除之類的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/**
* Wait until the test condition is true or a timeout occurs. Useful for waiting
* on a server response or for a ui change (fadeIn, etc.) to occur.
*
* @param testFx javascript condition that evaluates to a boolean,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param onReady what to do when testFx condition is fulfilled,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
*/
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 250); //< repeat check every 250ms
};

var page = require('webpage').create(),
system = require('system'),
edmid,
address;

edmid = system.args[1];
address = 'http://xxx.com.tw/'+ edmid;

// Open Twitter on 'sencha' profile and, onPageLoad, do...
page.open(address, function (status) {
// Check for page load success
if (status !== "success") {
console.log("Unable to access network");
} else {
// Wait for 'signin-dropdown' to be visible
waitFor(function() {
// Check in the page if a specific element is now visible
return page.evaluate(function() {
return ($("body").prop("class") == "allready" );
//return $("#signin-dropdown").is(":visible");
});
}, function() {
console.log("body allready now.");
page.render('D:\\test\\'+edmid+'.png');
phantom.exit();
});
}
});

解析Json格式時取得dynamic型別的物件,但如果裡面的物件不是用陣列的方式回傳,而是像這樣

我們不會知道.links底下究竟會link0、link1、link2….到幾,所以需要一個方法去try這個屬性是否存在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private object GetDynamicMember(object obj, string memberName)
{
try
{
var binder = Binder.GetMember(CSharpBinderFlags.None, memberName, obj.GetType(),
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
var callsite = CallSite<Func<CallSite, object, object>>.Create(binder);
return callsite.Target(callsite, obj);
}
catch (Exception ex)
{
return null;
}
}

透過這個方法,我們就可以試著將屬性丟進去看看有無回傳值了 ```csharp
int i = 0;
while (true)
{
dynamic trylink = GetDynamicMember(jsondata.links, “link” + i);
if (trylink != null)
{
_urlclickcount += Convert.ToInt32(trylink.clicks);
i++;
}
else
break;
}


之前POST資料都是在Client端無論是用JQuery的AJAX或是Form的方式,今天學會如何從Server端POST資料到指定的頁面,記錄一下程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//Post資料到Web
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(WebURL);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";

//將要傳遞的資料PostData轉成Byte陣列並寫入request
byte[] byWordWriteroPost = encoding.GetBytes(PostData);
request.ContentLength = byWordWriteroPost.Length;
Stream stream = request.GetRequestStream();
stream.Write(byWordWriteroPost, 0, byWordWriteroPost.Length);
stream.Close();

//取得網頁結果
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), encoding);
string returnString = reader.ReadToEnd();
response.Close();

做專案時常常會有測試機與正式機的區別,又兩者要呼叫的API常常也有正式與測試的區別。如果將網址寫死在Code裡,將造成佈署測試機時compile一次,佈署到正式機又要打開code改好網址後再compile一次,不僅耗時又容易出錯。

所以大部分有這種情況時會將網址參數寫在WebConfig裡,這樣只要到兩台機器去修改參數網址即可,避免了一再compile的問題。

1
2
3
4
5
<appSettings>
<add key="APIUrlTest" value="TestAPI.com.tw" />
<add key="APIUrl" value="xxx.com.tw" />
</appSettings>

但可能會有很多類似這種參數會寫在Config裡,網址、時間、變數…琳瑯滿目,寫到最後連RD自己也搞得亂七八糟,所以就會寫要將同類型的參數歸類整理一翻。接下來Demo如何將WebConfig隔離與整理。

  • 首先先在專案中新增一個新的Config檔,就暫且命名為i.config
  • 在這個i.config中寫下新的區段(這邊我創了一個新的區塊叫iconfig)
  • 接著到Web.Config註冊這個區段
      *   在configSections中註冊[![](http://4.bp.blogspot.com/-Fgx71lYcBws/UkprtA0ViaI/AAAAAAAAELY/07Mhjt5ygQ4/s1600/1.png)](http://4.bp.blogspot.com/-Fgx71lYcBws/UkprtA0ViaI/AAAAAAAAELY/07Mhjt5ygQ4/s1600/1.png)
    
    • 在appSettings區段下面註冊
  • 在code裡面抓取i.config參數值得方法 ```csharp
    public class iconfig
    {
    private static System.Collections.Hashtable iConfig = (System.Collections.Hashtable)System.Configuration.ConfigurationManager.GetSection(“iconfig”);
    public static string ReservationApi { get { return (string)iConfig[“ReservationApi”]; } }
    }

```
依照上述方法就可以將很多不同類型的參數分門別類的整理起來了!!!

  1. 首先透過NuGet安裝以下四個套件
  2. 打開WebConfig可以找到以下設定 ```xml //是否需要權限才能閱讀這個Log,當然是True啦!! //是否停用原本預設調用Log的"網址/elmah"路徑 //如果權限設定為true的話,何種role可以調用Log //那些登入者可以調用Log 多人時用逗號分開 //設定調用Elmah Log的MVC Route
1
2
3
4
5
6

3. 刪除掉WebConfig的以下區段,所有人都不法透過"網址/elmah.axd"來讀取Log檔案(包含本機) ```xml
<location path="elmah.axd" inheritInChildApplications="false">
...略...
</location>

  1. ELMAH還有很多不錯的功能,例如將錯誤Log寫到DB裡面去,或是主動寄信通知設定。但目前還用不上就先不研究了!!5. 實際上看到Log的紀錄
    按下Detail後的詳細資訊,說實在還滿棒的~

  1. View ```csharp
    @using (Html.BeginForm(“edit”, “group”, FormMethod.Post, new { enctype = “multipart/form-data” }))
    {
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

2. Controller,這邊特別注意<span style="color: blue;">HttpPostedFileBase</span> picture的參數名稱要與View file的name相同 ```csharp
public ActionResult AddExhibitionItem(string name, string sort,string stop ,HttpPostedFileBase picture)
{
string err= string.Empty;
if (ExhibitionUtilFactory.AddItem(name, sort, stop, picture, ref err))
{
return Content("<script>alert('新增成功');window.parent.closeDialog();</script>");
}
else {
TempData["alert"] = err;
return View();
}
}

  1. 如果是多檔上傳的話,View ```csharp
1
2
3
4
5
6
7
8
9

4. Controller ```csharp
public ActionResult AddExhibitionItem(string name, string sort,string stop ,IEnumerable<HttpPostedFileBase> picture)
{
foreach (var file in picture) {
............ }
}