[BlogEngine插件]对日志进行加密

2008-10-25

这里的对日志加密是指输入正确密码以后才能正常访问。
示例:
http://yibin.us/Archives/6035.aspx
密码:123456
针对于BlogEngine来说,可以用它丰富的插件机制来实现。

首先明确,完成这个插件需要做哪些工作:
1、数据表结构的变化。要增加密码项,“密码”字段当然是少不了了。
2、表结构的变化势必会引起Post实体类属性的变化。
3、Post.Serving时触发事件,该事件负责针对性的改变e.Body
4、认证的实现。
这里我用的是SqlServer数据库,打开be_Posts表,执行以下语句

ALTER TABLE dbo.be_Posts
ADD AccessPassword VARCHAR(100) NOT NULL DEFAULT ''
GO

对应地在BlogEngine.Core.Post中增加属性AccessPassword

private string _AccessPassword = string.Empty;
public string AccessPassword
{
get { return _AccessPassword; }
set {
if (_AccessPassword != value) MarkChanged("AccessPassword");
_AccessPassword = value;
}
}

这里的AccessPassword不为空表明该日志需要密码才能访问。当然,这里还得修改相应的数据访问层代码,来初始化AccessPassword字段。这里略去。
下一步编写插件,针对Post.Serving事件编写,全部代码:

[Extension("加密日志","1.0","yibin")]
public class ZPostAccessExtension : System.Web.SessionState.IRequiresSessionState
{
string cookiekey = string.Empty;
public ZPostAccessExtension()
{
Post.Serving += new EventHandler<ServingEventArgs>(Post_Serving);
}

void Post_Serving(object sender, ServingEventArgs e)
{
Post p = sender as Post;
if (HttpContext.Current.User.IsInRole("administrators") || HttpContext.Current.User.Identity.Name == p.Author)
return;
cookiekey = "POSTACCESS_" + p.Id;
//这里很关键,用Session来判断当前用户没有权限访问,如果指定的session存在,则直接退出,否则更改e.Body值。
if (HttpContext.Current.Session[cookiekey] != null)
{
return;
}
if (!string.IsNullOrEmpty(p.AccessPassword))
{
if (e.Location == ServingLocation.PostList)
{
e.Body = "加密日志,您无权查看";
}
else
{
e.Body = string.Format(@"<p class=""AccessPassword"">加密日志,请输入密码查阅</p><input type=""password"" name=""AccessPassword_{0}"" id=""AccessPassword_{0}"" class=""AccessPassword"" /><input type=""button"" value=""确定"" title=""确定"" onclick=""Check();""/>", p.PostIdentity);
e.Body = e.Body.Replace("<", "<").Replace(">", ">");  //这里要对已经HtmlEncode后的字符进行还原,否则显示不正确。
}
}
}
}

接下来就是实现认证这一步,我采用的是实现ICallbackEventHandler接口来进行无刷新操作。
先看很简单的js代码

<script type="text/javascript">
var accessMessage = document.getElementById('AccessMessage');
function Check()
{
accessMessage.style.display='block';
var pwd = '';
var panel = document.getElementById('AccessPassword_<%=Post.PostIdentity %>');  //DOM找到密码输入框
if(panel) {
pwd = panel.value;
}
if(pwd==''){
accessMessage.innerHTML='密码不能为空';
panel.focus();
return false;
}
accessMessage.innerHTML='正在验证......';
<%= Page.ClientScript.GetCallbackEventReference(this,"pwd","checkCallback","")%>;
}

function checkCallback(rValue) {
if(rValue=='error')
{
accessMessage.style.display='block';
accessMessage.innerHTML='密码认证失败';
setTimeout(function(){accessMessage.style.display='none';},2000);
}
else{
accessMessage.style.display='block';
accessMessage.innerHTML='验证成功';
setTimeout(function(){document.getElementById('entrybody_<%=Post.PostIdentity %>').innerHTML = rValue;},500);
setTimeout(function(){accessMessage.style.display='none';},3000);
}
}
function ServerError(error) {
alert(error);
}
</script>

.cs文件中的关于ICallbackEventHandler接口的实现

#region ICallbackEventHandler 成员
protected string _callback = string.Empty;
string ICallbackEventHandler.GetCallbackResult()
{
return _callback;
}

void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
if (Post.AccessPassword == eventArgument.Trim())
{
string SessionKey = "POSTACCESS_" + Post.Id;
HttpContext.Current.Session.Add(SessionKey, true);  //注意这里,当密码验证成功后写session
string path = Utils.RelativeWebRoot + "themes/" + BlogSettings.Instance.Theme + "/PostView.ascx";

PostViewBase postView = (PostViewBase)LoadControl(path);
postView.Post = Post;
postView.Location = ServingLocation.SinglePost;
_callback = postView.Body;   //此处仍然会执行Post.Serving 事件,但因为前面已经写入了Session,所以触发Post.Serving 事件时将直接返回日志内容。
//因为我想每次访问日志都需要输密码,所以,当正确返回日志内容后,清除掉该Session
HttpContext.Current.Session.Remove(SessionKey);
}
else
{
_callback = "error";
}
}

#endregion

OK,整个过程就是如此,很是简单吧。
同样的原理,可以实现类似于论坛的“回复后可见”同样的功能,如果想长时间维持日志的正常查看权,可将Session换成Cookie。
另外,BlogEngine默认在web.config中将enableSessionState设为了false,请一定要设为true,否则无法使用Session!
我就是没有认真看web.config,在Session的获取上大费周折。

密码保护:测试加密日志

2008-10-25

这是一篇受密码保护的文章。您需要提供访问密码:


放弃Vista SP1

2008-10-23

费力从MS上把vista sp1拖下来
结果安装了N次(N>10),都出现错误(0x8007000D)
无语了啊,google、baidu全试过了,网上讲的方法也用遍了,就是不奏效。
要不是因为sp1改进了vista复制文件超慢的这个大笑话,我还真不情愿安装。
这下倒好,让我彻底放弃了。
等以后安装windows 7或直接安装整合了sp1的喂死它。

正式启用“山寨版”域名,yibin001.com
所有文章均做了301永久性重定向,lemongtree.com域名会一直续费。

好多朋友说yibin001.com这个域名超级2,
我也没办法,苦于我的姓名太大众化,而且与中国一地名“宜宾”汉语拼音完全一致,只能用山寨版的了。

ImageCropper For .Net

2008-10-20

这是一个基于.Net的图片裁剪控件,使用比较广泛,如Gravatar中的头像上传与裁剪功能的实现。
当然Gravatar并不是用的这个控件。
今天在codeproject中无意发现的,觉得不错,拿来与大家分享一下。


裁剪后

基本参数:
MaintainAspectRatio,bool型,是否固定宽高比例进行裁剪。
CroppedImageHeight,int型,裁剪后的图片高
CroppedImageWidth,int型,裁剪后的图片宽
JpegQuality,int型,裁剪后的图片质量
裁剪时直接调用ImageCropper的Crop()方法即可。

下载地址:
http://www.uushare.com/user/yibin/file/899549

周末小叙

2008-10-19

十一后在上海的二个周末都做了宅男,
昨天8点整起床之后去了菜市场,战利品:
1、二只大闸蟹,近500g。
2、1200g大排
3、汤藕若干
4、茼蒿若干

上午10点开始煲莲藕排骨汤。
中午和晚上各清蒸一只蟹,我还是秉承了我一贯吃蟹的作风:只吃脚及那对大钳子。
晚上未买菜,喝汤+吃另一只大闸蟹。
阳澄湖的蟹还真不是吹的。
晚上顺便看了电影《画皮》,没啥观后感。

今日9:30起床,依旧去菜市场觅食,
上海青、口菇、苦瓜。
看完电影《致命罗密欧》及《农家小屋》
下午找人修窗户。

寻域名,结果:

yibin.name=> 已被注册 查看 到域名交易中心试试运气
yibin.mobi=> 已被注册 查看 到域名交易中心试试运气
yibin.net=> 已被注册 查看 到域名交易中心试试运气
yibin.com=> 已被注册 查看 到域名交易中心试试运气
yibin.org=> 已被注册 查看 到域名交易中心试试运气
yibin.info=> 已被注册 查看 到域名交易中心试试运气
yibin.me=> 已被注册 查看 到域名交易中心试试运气
yibin.asia=> 已被注册 查看 到域名交易中心试试运气
yibin.cc=> 已被注册 查看 到域名交易中心试试运气

无语了~~~

让.Net验证控件与自定义验证合作无间

2008-10-16

场景:
一个注册表单,其间有.Net自带的验证控件,但有一些验证必须得借助于另外的一些js,如验证是否复选了注册协议(这里为了说明,只举这样一个简单的例子)。
这样的话,会涉及到二次验证,第一次可能是.Net验证控件的验证,第二次会认证用户有没有复选注册协议,如何让这二者合作无间呢?
这里不得不提到.Net的Page_ClientValidate()函数,该函数返回当前Page页中的表单有没有通过Validate的验证.

新建一个Page页面,简单的放一些控件

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button"
ValidationGroup="submit" CausesValidation="True"
onclick="Button1_Click" />
<input type="checkbox" id="checkbox" />我已阅读注册协议
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ControlToValidate="TextBox1" Display="Dynamic" ErrorMessage="不能为空"
ValidationGroup="submit"></asp:RequiredFieldValidator>

页面呈现

TextBox留空,点击Button,会进行一次验证,当在TextBox中输入文本时,再点击提交,验证通过,引发OnClick事件,但用户是否复选了注册协议此处还未做判断。

此时需要我们手写验证函数了

<script type="text/javascript">
function test() {
var isCheck = document.getElementById('checkbox').checked;
if (isCheck) {
//Page_ClientValidate('submit'),这里有不同的ValidGroup,所以Page_ClientValidate传递是指定的GroupName
if (Page_ClientValidate('submit')) {
alert('验证成功');
return true;
}
}
else {
alert('您必须同意注册协议');
return false;
}

return false;
}
</script>

修改后的代码

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" ValidationGroup="submit" CausesValidation="True"
OnClientClick="return test();" OnClick="Button1_Click" />
<input type="checkbox" id="checkbox" />我已阅读注册协议
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="TextBox1"
Display="Dynamic" ErrorMessage="不能为空" ValidationGroup="submit"></asp:RequiredFieldValidator>

预览页面



到这里好像已经结束了,但查看html源代码会发现:

<input type="submit" name="Button1" value="Button"
onclick="return test();WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("Button1", "", true, "submit", "", false, false))" id="Button1" />

Button1除了有return test()外还有WebForm_DoPostBackWithOptions这样一段,很明显WebForm_DoPostBackWithOptions是不会被执行的,去掉这段也很简单,
将Button1的CausesValidation设为false即可。

当然,你也可以完全不用验证控件来实现。

整理了国庆期间的二张相片

2008-10-14

十一回武汉是背着相机的
准备去久违的、有着美好回忆的东湖,再留下一些印记。
只是太感慨于武汉的人多,实在是难以折腾。
今天整理了一下相机里的照片,才发现只有在飞机上拍的几张。



很喜欢这样的蓝色

调皮好动的小外甥女,回上海时她还哭了


苦练《memory》中

练习《Memory》

2008-10-13

曲谱已到手N长时间
http://yibin.us/Archives/6038.aspx

一直没认真练过
右手的指甲也因不玩琴而没有好好修整,左手的指甲也没有去掉。
今天重新翻出曲谱,调了调琴弦,剪了剪左手指甲。
右手指甲直接决定音色,光修右手指甲就共了近10分钟,剪短、修形、抛光……
整个曲子大致分为3部分,第一部分的一个大横按巨难,前后衔接总是不连贯。
连续弹30分钟就感觉左手按不住了,唉,远远不如几年前了。

整个曲谱难道不是很大,但有很强的音乐性。
希望能早早拿下。

Remoting端口意外关闭

2008-10-12

昨天在本地测试一个程序时遇到的。
情况是这样子的:
远端是一个控制台程序,开放的是tcp 8898端口。
客户端采用Remoting访问远端的tcp 8898端口,并进行远端相关方法的调用。
远端有齐全的日志处理,一旦出现错误会直接抛出,不会影响到下一轮的执行。
做测试时发现客户端调用远端失败,返回:由于目标机器积极拒绝,无法连接。
这个错误就是远端程序停止了或端口不对。
但远端的控制台程序并未停止。
cmd telnet 127.0.0.1 8898显示无法连接,看来是8898这个端口无法访问了。
重启控制台程序正常。
很奇怪,程序没有异常,但端口却意外地关闭而无法访问。

在csdn上也找到一篇类似的帖子
http://topic.csdn.net/t/20041112/16/3547923.html

不知道你用的是不是tcp信道,而且是windows2003或xp sp1后的作为服务器,就会出现这样的问题;
建议采用http信道,就应该不会有这样的问题;
这是windows2003和xp sp1的新安全机制导致的。

除此之外再也没有相关的内容,这种情况不常有,一个月偶尔会有一次。

不知道有没有朋友也遇到过类似的问题。

一句话博客

2008-09-29

好像很早以前就开始流行这种“一句话博客”
比如“叽歪”,还有各种“闪存”,如博客园社区的闪存。
人的心情是多变的,有时候想把心情写上来,却又发现无法长篇大论去描述;有时想发表一句感慨却又发现身边没有电脑。
闪存与叽歪弥补了这一点,可以绑定手机,只需发一条短信即可。
这也用上了,并在侧边栏显示了出来。
随时随地用手机表达我此刻所想、所行。

二双鞋没有一双能在雨天行走
一双是鞋边开了,另一双是鞋底破了,雨天随时会进水
趁着假期,今天去买了双鞋,再也不用受雨天的气了。
明天就要回汉了,想爸妈了也想奶奶了。
这次请了二天年假,一共可以休9天,但今天发现,这样的长假我却感到乏味~~~

最后祝各位国庆快乐。