.NET开发常见问题两则

179 views 九月 22, 07 by Timothy

一、关于DateTime
在将DateTime类型,插入到数据库的时候,最容易出现的一种错误:
“SqlDateTime 溢出。必须介于 1/1/1753 12:00:00 AM 和 12/31/9999 11:59:59 PM 之间”
原因是我们在取DateTime.MinValue的值,并插入到数据库的时候,DateTime.MinValue值范围和数据库DateTime类型数据范围不一致造成的。数据库中,DateTime类型字段,最小值1/1/1753 12:00:00,而.NET Framework中,DateTime类型,最小值为1/1/0001 0:00:00,显然,超出了Sql的值的最小范围,导致数据溢出的错误。

解决方法:使用System.Data.SqlTypes.SqlDateTime.MinValue替代System.DateTime类型,这样SqlDateTime的MinValue和Sql中DateTime的范围吻合,就不会再出现以上的错误了。

二、关于跨线程调用控件的问题
在.NET 2.0中,我们常常需要在新建的线程,比如一个工作线程中访问UI控件,程序编译没有任何错误,但是在运行的时候,会抛出异常:InvalidOperationException,并提示消息:“从不是创建控件 control name 的线程访问它。”
原因是因为:访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。.NET Framework 有助于在以非线程安全方式访问控件时检测到这一问题。

我们看看有问题的代码:建立新线程,并试图在线程中跨线程调用UI控件
[code]
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(TestFunc));
thread.IsBackground = true;
thread.Start();
}

private void TestFunc()
{
Thread.Sleep(3000);
label1.Text = "ok!";
}

[/code]

这样在运行的时候,就会抛出InvalidOperationException异常。

解决方法:
方法1.关闭跨线程调用控件的检查,来屏蔽掉此异常
需要将Control.CheckForIllegalCrossThreadCalls 设为 false即可。(不推荐)

方法2.使用Control类的Invoke和BeginInvoke
为什么使用Invoke和BeginInvoke可以解决问题呢?因为Control的Invoke和BeginInvoke的参数为delegate,委托的方法是在Control的线程上执行的,也就是我们平时所说的UI线程。而控件也是在UI线程,所以不存在跨线程调用控件的问题。于是我们有了改进的代码:

[code]
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(TestFunc));
thread.IsBackground = true;
thread.Start();
}

private void TestFunc()
{
Thread.Sleep(3000);
this.Invoke(new SetLabel(SetLabelText), new string[] { "ok!" });
}

private delegate void SetLabel(string s);

private void SetLabelText(string s)
{
label1.Text = s;
}

[/code]

建立一个委托,调用Control类的Invoke方法,让UI线程去执行委托实例化的方法。这样就不会出现异常了。

换了个新的网站空间

189 views 九月 17, 07 by Timothy

博客恢复运行了。
这也是开站以来,第一次网站大搬家。无奈,为了能恢复博客,不得不换个空间。
新空间速度也不错,价格方面,也比以前省银子,而且是个全能空间,包括支持ASP.NET :-) 容量也比以前的大,还是值得高兴。

给大家推荐一下 联动中国 http://www.winhost.cn

周末的榴莲大餐

284 views 九月 01, 07 by Timothy

买回家的榴莲,放了两天,终于熟了,回家后马上开工……
今晚可过足了瘾……

放熟的榴莲,不用费力气,自己会裂开的。打开坚硬的外科,露出黄黄的果肉来


使劲掰开来,果肉完全呈现

大卸八块,将果肉全部取出

———————-我是华丽的分隔线———————-
附上榴莲选购食用技巧:

榴莲以外形多丘?状的为上选,因为每个丘状面会一颗核;有果核必有果肉,丘状较多的就可保证有较多的果肉。
首先看看尾部的刺,越密越细越好;接著用鼻子贴近闻,有浓厚香气者为佳;最后以手用力摇动,听到咚咚响声表示已经成熟了。
榴莲的壳变黄,刺有一点软,最好是稍微有点裂开的(是自然裂开,不是因外力而裂的),外壳散发出榴莲香的那一种最好。

果内有“干包”、“湿包”之分。购买榴莲时,一定要看表面刺的疏密,刺密肉少,刺疏肉才厚。还需看颜色深浅,太深,则过熟;太浅,则未成熟;不深不浅为宜。要选干包的,干包爽口,甜而不腻,湿包粘口且腻。如果买了湿包的,吃时,先用水把手浸湿,以免粘手。

轻摇榴莲有声音时,代表它已可以吃了 。
挑外表像狼牙棒的,有一股股小山邱鼎起来的.小山越多肉越多.壳有点开了的是熟了的,比较甜比较好吃,但壳开的时间不能太长,熟过头了就是腐烂了。
挑选好吃的金枕头榴连, 首先留意果形,外表一定要长形的,尾部的外型是长尖形,如此则皮薄肉丰满,籽也会比较小。 色泽最好是淡黄绿色或金黄色,
至于熟度,可闻闻尾巴处,如果有浓浓的果肉香,当天就可吃,若闻起来味道较淡,则多放几天再吃。
另外提供一个简易吃法:取螺丝起子在榴连尾端插入后上下左右摇摆,果实产生裂缝时,即可剥开享用

PJBlog恶意广告POST漏洞之测试与修复

189 views 八月 30, 07 by Timothy

今天在网上找了一个Vista的皮肤,赶紧给我的BLOG换上,漂亮了许多,呵呵。
最近BLOG上,广告多得吓人,特别是在文章的评论和留言本里面,真是无孔不入的广告。由于偶比较痛恨这些广告,手动删除也不是办法,整页整页的广告评论和留言,多则上百条。而且手动在管理界面删除,也只是一个治标不治本的办法。
据寡人分析[biggrin],可能是评论和留言的post环节不够强悍,导致垃圾广告有孔而入。不过这个BLOG的评论和留言都是有验证码的,评论的POST对应于blogcomm.asp文件,评论的页面,通过指向GetCode.asp,获取验证码图片,并在Session中保存该验证码,用以和用户输入的验证码比对。
那么如果要达到用程序,自动提交垃圾广告,可以想到的方法有两种:
1.用程序识别图片验证码,获取其内容,然后模拟POST。不过这个比较高难,要程序识别图片中的数字,需要图形识别的知识。
2.绕过验证码的过程,直接POST。这个要根据具体的漏洞而定。

于是随手在google上搜索了一下,PJBlog还真有这个漏洞。[eek]

具体的漏洞描述如下:
blogcomm.asp文件对验证码判断不严格。
如果用户没有请求过GetCode.asp文件,那么服务器端Session里面的GetCode值为空,而用户提交的数据里面验证码也为空,这样刚好空等于空,反而通过了验证码验证。

查看blogcomm.asp源码,在Line 94行有这样的情况。

为了验证这个漏洞是否存在,我们可以自己动手测试一下,用程序模拟POST一次。就拿偶的BLOG做实验吧。首先,随便打开一个文章,启动网络抓包工具,(这里我用的是WSE–WinSocketExpert),随便敲入几个字,查看捕获下来的网络包。我们会发现,POST的数据格式是这样的:

username=Timothy&password=&Message=PostData&logID=171&action=post&submit2=%E5%8F%91%E8%A1%A8%E8%AF%84%E8%AE%BA

username 是评论者名称
password 是密码(游客不需要密码)
logID 就是文章编号
Message 就是评论内容了,垃圾广告最关注的就是这个……
action 是一个隐藏的field,值为post,这个可以在页面上通过查看源码看到
submit2 后面的码,转换成中文,其实就是“发表评论”,同样参考评论页面源码

POST的结构知道了,下面我们用程序来模拟POST一下,看漏洞是否存在,测试代码如下:
(请慎用此部分代码,不要用于垃圾广告软件,谢谢 [cool])

[code]private void PostFunc()
{

WebClient wc = new WebClient();

string postData = "username=Timothy&password=&Message=PostData&logID=171&action=post&submit2=%E5%8F%91%E8%A1%A8%E8%AF%84%E8%AE%BA";
try
{
wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
wc.UploadData("http://www.xiaozhou.net/cooldog/blogcomm.asp", "POST", Encoding.Default.GetBytes(postData));
}
catch
{
wc.Dispose();
return;
}

wc.Dispose();
}[/code]

运行此程序,可以在我的blog的编号171的文章评论中,看到下图:

看来漏洞真的存在……
这里,我们可以看到POST数据结构中,logID是可以人为改变的,也就是文章编号。如果把logID作为变量自增,测试代码外面,再套一个for循环,这个程序就成了制造垃圾广告的机器了……

找到了漏洞,得赶紧补上才行。其实我们需要修改的地方,就是在blogcomm.asp。找到94行,这里的判断,由于没有对Session进行判断才导致了此漏洞的产生。
修改方法如下:
blogcomm.asp Line:94
原代码:

IF (memName=empty or blog_validate=true) and cstr(lcase(Session("GetCode")))<>cstr(lcase(validate)) then

替换后的代码,增加对Session的判断:

IF (memName=empty or blog_validate=true) and (cstr(lcase(Session("GetCode")))<>cstr(lcase(validate)) or IsEmpty(Session("GetCode"))) then

大功告成了……[cool]睡觉去……

杂记

138 views 八月 28, 07 by Timothy

站点前几天访问不了,网上问了空间提供商,原来是机房被查封了,郁闷。还好,现在终于恢复了。
最近工作不像前几个月那么忙了,值得庆幸的是,项目达标通过了,大家心里都松了一口气。看来这几个月的努力没有白费,想起往日的加班,凌晨坐出租车回家,往事历历在目,不忍回首啊……
昨天和老婆去好又多,遇到榴莲搞促销,一口气买了两个榴莲搬回家,这下可以过足瘾了。其实我当初也不喜欢榴莲,可是吃着吃着就吃出感情了,越吃越觉得好吃。
今天把我的blog的音乐也更新了,换成了St.Philips.Boys的作品,天使般的声音,我很喜欢。
帮我老哥做的站点基本完工了,卖年画的站点,大家有空多去碰碰场
泥香久久 www.nixiangjiujiu.cn