<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>幻想曲.Net &#187; blogengine</title>
	<atom:link href="http://yibin.us/tag/blogengine/feed" rel="self" type="application/rss+xml" />
	<link>http://yibin.us</link>
	<description>曾经沧海难为水，除却巫山不是云</description>
	<lastBuildDate>Tue, 15 May 2012 14:31:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Blog转换至WordPress</title>
		<link>http://yibin.us/archives/6113</link>
		<comments>http://yibin.us/archives/6113#comments</comments>
		<pubDate>Sat, 02 May 2009 09:14:21 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[笔记本子]]></category>
		<category><![CDATA[blogengine]]></category>
		<category><![CDATA[wp]]></category>

		<guid isPermaLink="false">http://yibin.us/?p=6113</guid>
		<description><![CDATA[已从Blogengine完整转到wp程序 顺便把apple的也给转了. 日志与评论均已转换，分类就没有转了。 链接方面也没有转，准备手工加一下。 所有的日志链接已做301跳转， ps,wp后台发布日志真叫慢啊。。]]></description>
			<content:encoded><![CDATA[<p>已从Blogengine完整转到wp程序<br />
顺便把<a href="http://www.iceapple.net" target="_blank">apple</a>的也给转了.</p>
<p>日志与评论均已转换，分类就没有转了。</p>
<p>链接方面也没有转，准备手工加一下。</p>
<p>所有的日志链接已做301跳转，</p>
<p>ps,wp后台发布日志真叫慢啊。。</p>
]]></content:encoded>
			<wfw:commentRss>http://yibin.us/archives/6113/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>[BlogEngine扩展]IP2Area</title>
		<link>http://yibin.us/archives/6049</link>
		<comments>http://yibin.us/archives/6049#comments</comments>
		<pubDate>Fri, 05 Dec 2008 13:33:23 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Asp.Net]]></category>
		<category><![CDATA[blogengine]]></category>

		<guid isPermaLink="false">http://yibin.us/?p=6049</guid>
		<description><![CDATA[该插件将评论者的IP转为地区，数据取自于http://www.ip138.com在这里表示感谢！该扩展要在CommentAdded事件上进行处理，首先添加一个字段UserArea用来保存地区。放心，这里的是异步处理的，不会造成页面的明显延迟。 代码如下： /// &#60;summary&#62; ///Ip2Area 的摘要说明 /// &#60;/summary&#62; /// [Extension("IP转为地区", "1.0", "JasonYi")] public class Ip2Area { public Ip2Area() { Post.CommentAdded += new EventHandler&#60;EventArgs&#62;(Post_CommentAdded); } void Post_CommentAdded(object sender, EventArgs e) { Comment p = sender as Comment; if(p!=null) new HttpAsyncGetIPArea(p,"http://www.ip138.com/ips.asp").Execute(); } } public class HttpAsyncGetIPArea { private Comment _comment; private string _url; public HttpAsyncGetIPArea(Comment c,string url) [...]]]></description>
			<content:encoded><![CDATA[<p>该插件将评论者的IP转为地区，数据取自于<a href="http://www.ip138.com" target="_blank">http://www.ip138.com</a><br />在这里表示感谢！<br />该扩展要在CommentAdded事件上进行处理，首先添加一个字段UserArea用来保存地区。<br />放心，这里的是异步处理的，不会造成页面的明显延迟。</p>
<p>代码如下：<br /><code><br />
/// &lt;summary&gt;<br />
///Ip2Area 的摘要说明<br />
/// &lt;/summary&gt;<br />
///<br />
[Extension("IP转为地区", "1.0", "JasonYi")]<br />
public class Ip2Area<br />
{<br />
    public Ip2Area()<br />
    {<br />
        Post.CommentAdded += new EventHandler&lt;EventArgs&gt;(Post_CommentAdded);<br />
    }</p>
<p>    void Post_CommentAdded(object sender, EventArgs e)<br />
    {<br />
        Comment p = sender as Comment;<br />
        if(p!=null)<br />
        new HttpAsyncGetIPArea(p,"http://www.ip138.com/ips.asp").Execute();<br />
    }<br />
}<br />
public class HttpAsyncGetIPArea<br />
{<br />
    private Comment _comment;<br />
    private string _url;<br />
    public HttpAsyncGetIPArea(Comment c,string url)<br />
    {<br />
        _comment = c;<br />
        _url = url;<br />
    }<br />
    public Comment comment<br />
    {<br />
        get { return _comment; }<br />
    }<br />
    private HttpWebRequest Request;</p>
<p>    public void Execute()<br />
    {<br />
        Request = (HttpWebRequest)WebRequest.Create(_url);<br />
        Request.Method = "POST";<br />
        Request.ContentType = "application/x-www-form-urlencoded";<br />
        Byte[] data = System.Text.Encoding.ASCII.GetBytes("action=2&#038;ip=" + _comment.IP);<br />
        Request.ContentLength = data.Length;<br />
        using (Stream stream = Request.GetRequestStream())<br />
        {<br />
            stream.Write(data, 0, data.Length);<br />
        }<br />
        Request.BeginGetResponse(ProcessRespose, this);<br />
    }<br />
    private void ProcessRespose(IAsyncResult async)<br />
    {<br />
        HttpAsyncGetIPArea item = (HttpAsyncGetIPArea)async.AsyncState;<br />
        try<br />
        {<br />
            using (HttpWebResponse response = (HttpWebResponse)item.Request.EndGetResponse(async))<br />
            {<br />
                string RStr = string.Empty;</p>
<p>                using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.Default))<br />
                {</p>
<p>                    RStr = sr.ReadToEnd();<br />
                }<br />
                Regex reg = new Regex(@"本站主数据：([^&lt;li&gt;]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);<br />
                MatchCollection mc = reg.Matches(RStr);<br />
                string area = string.Empty;<br />
                if (mc.Count &gt; 0)<br />
                {<br />
                    area = mc[0].Value.Replace("本站主数据：", string.Empty);<br />
                }<br />
                if (!string.IsNullOrEmpty(area))<br />
                {<br />
                    string sql = "UPDATE  be_PostComment SET UserArea=@Area WHERE PostCommentID=@Id";<br />
                    SqlParameter[] para = { new SqlParameter("@Area", area), new SqlParameter("@Id", comment.Id) };<br />
                    SqlHelper.ExecuteNonQuery(SqlHelper.ConnectionString, System.Data.CommandType.Text, sql, para);<br />
                    comment.UserArea = area;<br />
                }<br />
            }<br />
        }<br />
        catch (Exception ex)<br />
        {<br />
            //throw new System.Net.WebException("Get HttpResponse Error");<br />
        }<br />
        finally<br />
        {<br />
            Request.Abort();<br />
        }<br />
    }<br />
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://yibin.us/archives/6049/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>[BlogEngine插件]对日志进行加密</title>
		<link>http://yibin.us/archives/6036</link>
		<comments>http://yibin.us/archives/6036#comments</comments>
		<pubDate>Sat, 25 Oct 2008 07:32:54 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Asp.Net]]></category>
		<category><![CDATA[blogengine]]></category>

		<guid isPermaLink="false">http://yibin.us/?p=6036</guid>
		<description><![CDATA[这里的对日志加密是指输入正确密码以后才能正常访问。 示例： http://yibin.us/Archives/6035.aspx 密码：123456 针对于BlogEngine来说，可以用它丰富的插件机制来实现。 首先明确，完成这个插件需要做哪些工作： １、数据表结构的变化。要增加密码项，“密码”字段当然是少不了了。 ２、表结构的变化势必会引起Post实体类属性的变化。 ３、Post.Serving时触发事件，该事件负责针对性的改变e.Body 4、认证的实现。 这里我用的是SqlServer数据库，打开be_Posts表，执行以下语句 对应地在BlogEngine.Core.Post中增加属性AccessPassword 这里的AccessPassword不为空表明该日志需要密码才能访问。当然，这里还得修改相应的数据访问层代码，来初始化AccessPassword字段。这里略去。 下一步编写插件，针对Post.Serving事件编写，全部代码： 接下来就是实现认证这一步，我采用的是实现ICallbackEventHandler接口来进行无刷新操作。 先看很简单的js代码 .cs文件中的关于ICallbackEventHandler接口的实现 OK，整个过程就是如此，很是简单吧。 同样的原理，可以实现类似于论坛的“回复后可见”同样的功能，如果想长时间维持日志的正常查看权，可将Session换成Cookie。 另外，BlogEngine默认在web.config中将enableSessionState设为了false，请一定要设为true,否则无法使用Session! 我就是没有认真看web.config，在Session的获取上大费周折。]]></description>
			<content:encoded><![CDATA[<p>这里的对日志加密是指输入正确密码以后才能正常访问。<br />
示例：<br />
<a href="http://yibin.us/Archives/6035.aspx" target="_blank">http://yibin.us/Archives/6035.aspx</a><br />
密码：123456<br />
针对于BlogEngine来说，可以用它丰富的插件机制来实现。</p>
<p>首先明确，完成这个插件需要做哪些工作：<br />
１、数据表结构的变化。要增加密码项，“密码”字段当然是少不了了。<br />
２、表结构的变化势必会引起Post实体类属性的变化。<br />
３、Post.Serving时触发事件，该事件负责针对性的改变e.Body<br />
4、认证的实现。<br />
这里我用的是SqlServer数据库，打开be_Posts表，执行以下语句</p>
<pre class="brush: sql; title: ; notranslate">
ALTER TABLE dbo.be_Posts
ADD AccessPassword VARCHAR(100) NOT NULL DEFAULT ''
GO
</pre>
<p>对应地在BlogEngine.Core.Post中增加属性AccessPassword</p>
<pre class="brush: csharp; title: ; notranslate">
private string _AccessPassword = string.Empty;
public string AccessPassword
{
get { return _AccessPassword; }
set {
if (_AccessPassword != value) MarkChanged(&amp;quot;AccessPassword&amp;quot;);
_AccessPassword = value;
}
}
</pre>
<p>这里的AccessPassword不为空表明该日志需要密码才能访问。当然，这里还得修改相应的数据访问层代码，来初始化AccessPassword字段。这里略去。<br />
下一步编写插件，针对Post.Serving事件编写，全部代码：</p>
<pre class="brush: csharp; title: ; notranslate">
[Extension(&amp;quot;加密日志&amp;quot;,&amp;quot;1.0&amp;quot;,&amp;quot;yibin&amp;quot;)]
public class ZPostAccessExtension : System.Web.SessionState.IRequiresSessionState
{
string cookiekey = string.Empty;
public ZPostAccessExtension()
{
Post.Serving += new EventHandler&amp;lt;ServingEventArgs&amp;gt;(Post_Serving);
}

void Post_Serving(object sender, ServingEventArgs e)
{
Post p = sender as Post;
if (HttpContext.Current.User.IsInRole(&amp;quot;administrators&amp;quot;) || HttpContext.Current.User.Identity.Name == p.Author)
return;
cookiekey = &amp;quot;POSTACCESS_&amp;quot; + 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 = &amp;quot;加密日志,您无权查看&amp;quot;;
}
else
{
e.Body = string.Format(@&amp;quot;&amp;lt;p class=&amp;quot;&amp;quot;AccessPassword&amp;quot;&amp;quot;&amp;gt;加密日志，请输入密码查阅&amp;lt;/p&amp;gt;&amp;lt;input type=&amp;quot;&amp;quot;password&amp;quot;&amp;quot; name=&amp;quot;&amp;quot;AccessPassword_{0}&amp;quot;&amp;quot; id=&amp;quot;&amp;quot;AccessPassword_{0}&amp;quot;&amp;quot; class=&amp;quot;&amp;quot;AccessPassword&amp;quot;&amp;quot; /&amp;gt;&amp;lt;input type=&amp;quot;&amp;quot;button&amp;quot;&amp;quot; value=&amp;quot;&amp;quot;确定&amp;quot;&amp;quot; title=&amp;quot;&amp;quot;确定&amp;quot;&amp;quot; onclick=&amp;quot;&amp;quot;Check();&amp;quot;&amp;quot;/&amp;gt;&amp;quot;, p.PostIdentity);
e.Body = e.Body.Replace(&amp;quot;&amp;lt;&amp;quot;, &amp;quot;&amp;lt;&amp;quot;).Replace(&amp;quot;&amp;gt;&amp;quot;, &amp;quot;&amp;gt;&amp;quot;);  //这里要对已经HtmlEncode后的字符进行还原，否则显示不正确。
}
}
}
}
</pre>
<p>接下来就是实现认证这一步，我采用的是实现ICallbackEventHandler接口来进行无刷新操作。<br />
先看很简单的js代码</p>
<pre class="brush: jscript; title: ; notranslate">
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
var accessMessage = document.getElementById('AccessMessage');
function Check()
{
accessMessage.style.display='block';
var pwd = '';
var panel = document.getElementById('AccessPassword_&amp;lt;%=Post.PostIdentity %&amp;gt;');  //DOM找到密码输入框
if(panel) {
pwd = panel.value;
}
if(pwd==''){
accessMessage.innerHTML='密码不能为空';
panel.focus();
return false;
}
accessMessage.innerHTML='正在验证......';
&amp;lt;%= Page.ClientScript.GetCallbackEventReference(this,&amp;quot;pwd&amp;quot;,&amp;quot;checkCallback&amp;quot;,&amp;quot;&amp;quot;)%&amp;gt;;
}

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_&amp;lt;%=Post.PostIdentity %&amp;gt;').innerHTML = rValue;},500);
setTimeout(function(){accessMessage.style.display='none';},3000);
}
}
function ServerError(error) {
alert(error);
}
&amp;lt;/script&amp;gt;
</pre>
<p>.cs文件中的关于ICallbackEventHandler接口的实现</p>
<pre class="brush: csharp; title: ; notranslate">
#region ICallbackEventHandler 成员
protected string _callback = string.Empty;
string ICallbackEventHandler.GetCallbackResult()
{
return _callback;
}

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

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 = &amp;quot;error&amp;quot;;
}
}

#endregion
</pre>
<p>OK，整个过程就是如此，很是简单吧。<br />
同样的原理，可以实现类似于论坛的“回复后可见”同样的功能，如果想长时间维持日志的正常查看权，可将Session换成Cookie。<br />
<span style="color: red;">另外，BlogEngine默认在web.config中将enableSessionState设为了false，请一定要设为true,否则无法使用Session!</span><br />
我就是没有认真看web.config，在Session的获取上大费周折。</p>
]]></content:encoded>
			<wfw:commentRss>http://yibin.us/archives/6036/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>密码保护：测试加密日志</title>
		<link>http://yibin.us/archives/6035</link>
		<comments>http://yibin.us/archives/6035#comments</comments>
		<pubDate>Sat, 25 Oct 2008 06:47:31 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[Asp.Net]]></category>
		<category><![CDATA[blogengine]]></category>

		<guid isPermaLink="false">http://yibin.us/?p=6035</guid>
		<description><![CDATA[无法提供摘要。这是一篇受保护的文章。]]></description>
			<content:encoded><![CDATA[<form action="http://yibin.us/wp-pass.php" method="post">
<p>这是一篇受密码保护的文章。您需要提供访问密码：</p>
<p><label for="pwbox-6035">密码：<br />
<input name="post_password" id="pwbox-6035" type="password" size="20" /></label><br />
<input type="submit" name="Submit" value="提交" /></p></form>
]]></content:encoded>
			<wfw:commentRss>http://yibin.us/archives/6035/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>浅谈BlogEngine扩展机制的实现</title>
		<link>http://yibin.us/archives/5996</link>
		<comments>http://yibin.us/archives/5996#comments</comments>
		<pubDate>Tue, 29 Jul 2008 06:08:13 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Asp.Net]]></category>
		<category><![CDATA[blogengine]]></category>

		<guid isPermaLink="false">http://yibin.us/?p=5996</guid>
		<description><![CDATA[以前写过一个针对于Blogengine的Mp3播放器扩展在Blogengine里，每一个扩展的Class都必须有Extension标记ExtensionAttribute是一个密封类，继承自System.Attribute,System.Attribute没有任何实现，只是一个标记而已。ExtensionAttribute类的代码: [AttributeUsage(AttributeTargets.Class)] //指明该Attrubite只能应用于Class上 public sealed class ExtensionAttribute : System.Attribute { /// &#60;summary&#62; /// Creates an instance of the attribute and assigns a description. /// &#60;/summary&#62; public ExtensionAttribute(string description, string version, string author) { _Description = description; _Version = version; _Author = author; } private string _Description; /// &#60;summary&#62; /// Gets the description of the extension. [...]]]></description>
			<content:encoded><![CDATA[<p>以前写过一个针对于Blogengine的<a href="http://yibin.us/Archives/BlogEngineNET_Extensions_mp3player.aspx" target="_blank">Mp3播放器扩展</a><br />在Blogengine里，每一个扩展的Class都必须有<b>Extension</b>标记<br />ExtensionAttribute是一个密封类，继承自System.Attribute,System.Attribute没有任何实现，只是一个标记而已。<br />ExtensionAttribute类的代码:<br /><code><br />
[AttributeUsage(AttributeTargets.Class)]  //指明该Attrubite只能应用于Class上<br />
  public sealed class ExtensionAttribute : System.Attribute<br />
  {<br />
    /// &lt;summary&gt;<br />
    /// Creates an instance of the attribute and assigns a description.<br />
    /// &lt;/summary&gt;<br />
    public ExtensionAttribute(string description, string version, string author)<br />
    {<br />
      _Description = description;<br />
      _Version = version;<br />
      _Author = author;<br />
    }</p>
<p>    private string _Description;<br />
    /// &lt;summary&gt;<br />
    /// Gets the description of the extension.<br />
    /// &lt;/summary&gt;<br />
    public string Description<br />
    {<br />
      get { return _Description; }<br />
    }</p>
<p>    private string _Version;</p>
<p>    /// &lt;summary&gt;<br />
    /// Gets the version number of the extension<br />
    /// &lt;/summary&gt;<br />
    public string Version<br />
    {<br />
      get { return _Version; }<br />
    }</p>
<p>    private string _Author;</p>
<p>    /// &lt;summary&gt;<br />
    /// Gets the author of the extension<br />
    /// &lt;/summary&gt;<br />
    public string Author<br />
    {<br />
      get { return _Author; }<br />
    }</p>
<p>  }
</pre>
<p>这个类非常之简单，只是一些描述性的信息，如作者、版本、描述等。<br />到这里，ExtensionAttribute类就可以应用在任何一个Class上了<br />看看mp3player.cs<br /><code><br />
/// &lt;summary&gt;<br />
/// 增加flashMp3播放器<br />
/// &lt;/summary&gt;<br />
[Extension("mp3 player", "1.0.0.0", "lemongtree.com")]  //此处给mp3player类打上Extension标记<br />
public class mp3player<br />
{<br />
    public mp3player()<br />
    {<br />
        Post.Serving += new EventHandler&lt;ServingEventArgs&gt;(Post_Serving);<br />
    }<br />
    private void Post_Serving(object sender, ServingEventArgs e)<br />
    {<br />
        //此处略过<br />
    }<br />
}
</pre>
<p>mp3player就是一个针对于Post的扩展了。<br />有朋友可能会问了:mp3player这个在什么时候实例化的呢？或是我如何得知这个扩展是不是Enable的呢?<br />整个实例化的过程在global.asax的Application_Start事件中<br /><code><br />
Assembly a = Assembly.Load(assemblyName);<br />
      Type[] types = a.GetTypes();   //获取当前程序集中的所有类型</p>
<p>      foreach (Type type in types)<br />
      {<br />
        object[] attributes = type.GetCustomAttributes(typeof(ExtensionAttribute), false);   //获取含有ExtensionAttribute标记的类<br />
        foreach (object attribute in attributes)<br />
        {<br />
          if (ExtensionManager.ExtensionEnabled(type.Name))<br />
          {<br />
            a.CreateInstance(type.FullName);  //创建实例<br />
          }<br />
        }<br />
      }
</pre>
<p>到这里很明了了，扩展类决定于它有没有打Extension标记，是否创建实例取决于该扩展有没有被启用.<br />BlogEngine有很多地方是值得我们学习的.</p>
]]></content:encoded>
			<wfw:commentRss>http://yibin.us/archives/5996/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>SqlMemberShip RoleProvider for blogengine</title>
		<link>http://yibin.us/archives/5995</link>
		<comments>http://yibin.us/archives/5995#comments</comments>
		<pubDate>Mon, 28 Jul 2008 15:47:25 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Asp.Net]]></category>
		<category><![CDATA[blogengine]]></category>

		<guid isPermaLink="false">http://yibin.us/?p=5995</guid>
		<description><![CDATA[自上次完成SqlDataProvider后今天再次完成SqlMembershipProvider及RoleProvider表结构be_Users表 CREATE TABLE [dbo].[be_users]( [UserID] [int] IDENTITY(1000,1) NOT NULL, [UserName] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL CONSTRAINT [DF_be_users_UserName] DEFAULT (''), [UserPassword] [varchar](100) COLLATE Chinese_PRC_CI_AS NOT NULL CONSTRAINT [DF_be_users_UserPassword] DEFAULT (''), [UserEmail] [varchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL CONSTRAINT [DF_be_users_UserEmail] DEFAULT (''), CONSTRAINT [PK_be_users] PRIMARY KEY CLUSTERED ( [UserID] ASC )WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [...]]]></description>
			<content:encoded><![CDATA[<p>自上次完成SqlDataProvider后<br />今天再次完成SqlMembershipProvider及RoleProvider<br />表结构<br />be_Users表<br /><code><br />
CREATE TABLE [dbo].[be_users](<br />
	[UserID] [int] IDENTITY(1000,1) NOT NULL,<br />
	[UserName] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL CONSTRAINT [DF_be_users_UserName]  DEFAULT (''),<br />
	[UserPassword] [varchar](100) COLLATE Chinese_PRC_CI_AS NOT NULL CONSTRAINT [DF_be_users_UserPassword]  DEFAULT (''),<br />
	[UserEmail] [varchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL CONSTRAINT [DF_be_users_UserEmail]  DEFAULT (''),<br />
 CONSTRAINT [PK_be_users] PRIMARY KEY CLUSTERED<br />
(<br />
	[UserID] ASC<br />
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]<br />
) ON [PRIMARY]
</pre>
<p>be_roles表<br /><code><br />
CREATE TABLE [dbo].[be_Roles](<br />
	[RoleID] [int] IDENTITY(1,1) NOT NULL,<br />
	[RoleName] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL CONSTRAINT [DF_be_Roles_RoleName]  DEFAULT (''),<br />
 CONSTRAINT [PK_be_Roles] PRIMARY KEY CLUSTERED<br />
(<br />
	[RoleID] ASC<br />
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]<br />
) ON [PRIMARY]
</pre>
<p>be_UserRole表<br /><code><br />
CREATE TABLE [dbo].[be_UserRole](<br />
	[ID] [int] IDENTITY(1,1) NOT NULL,<br />
	[UserName] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,<br />
	[RoleName] [varchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,<br />
 CONSTRAINT [PK_be_UserRole] PRIMARY KEY CLUSTERED<br />
(<br />
	[ID] ASC<br />
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]<br />
) ON [PRIMARY]
</pre>
<p>代码下载:<br /><a href="http://yibin.us/wp-content/uploads/20080728/MSSqlProvider.rar" target="_blank" class="download">MSSqlProvider.rar (12.60 kb)</a><br />修改web.config<br /><code><br />
......<br />
&lt;membership defaultProvider="MsSqlMembershipProvider"&gt;<br />
			&lt;providers&gt;<br />
				&lt;clear/&gt;<br />
				&lt;add name="XmlMembershipProvider" type="BlogEngine.Core.Providers.XmlMembershipProvider, BlogEngine.Core" description="XML membership provider" xmlFileName="~/App_Data/users.xml"/&gt;<br />
        &lt;add name="MsSqlMembershipProvider" type="BlogEngine.Core.Providers.MSSqlProvider.MsSqlMembershipProvider,BlogEngine.Core" description="Sql membership provider"/&gt;<br />
			&lt;/providers&gt;<br />
		&lt;/membership&gt;<br />
		&lt;roleManager defaultProvider="SqlRoleProvider" enabled="true" cacheRolesInCookie="true" cookieName=".BLOGENGINEROLES"&gt;<br />
			&lt;providers&gt;<br />
				&lt;clear/&gt;<br />
				&lt;add name="XmlRoleProvider" type="BlogEngine.Core.Providers.XmlRoleProvider, BlogEngine.Core" description="XML role provider" xmlFileName="~/App_Data/roles.xml"/&gt;<br />
        &lt;add name="SqlRoleProvider" type="BlogEngine.Core.Providers.MSSqlProvider.SqlRoleProvider,BlogEngine.Core" description="" /&gt;<br />
			&lt;/providers&gt;<br />
		&lt;/roleManager&gt;<br />
......
</pre>
]]></content:encoded>
			<wfw:commentRss>http://yibin.us/archives/5995/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>BlogEngine.NET js.axd bug</title>
		<link>http://yibin.us/archives/5932</link>
		<comments>http://yibin.us/archives/5932#comments</comments>
		<pubDate>Tue, 15 Apr 2008 12:25:00 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[blogengine]]></category>

		<guid isPermaLink="false">http://yibin.us/?p=5932</guid>
		<description><![CDATA[在gmail的垃圾邮件里找到一封标题为《网站有漏洞哦》的邮件，好奇地打开邮件，内容是： 详细的参考： http://blog.119797.com/post/BlogEngine-fix-js-Download-bug.aspx &#8211; by benben 由于涉及到链接，不敢用ie，用firefox打开一看，是一篇名为BlogEngine.NET js.axd 模块漏洞及修复的文章，往下一看，果然在js.axd文件有致命的bug，该bug可以让攻击者拿到用户名及密码，有了这些，等于完全操纵了你的blog程序，可怕！ Bug分析： js.axd文件是一个实现了IHttpHandler接口的处理文件，它的作用是将指定的js文件进行压缩与缓存，该文件需要传递一个path参数，如：js.axd?path=xxx.js，js.axd就会将xxx.js文件中的空白去掉以减小js文件的体积。 部分方法： 但这里出现的bug就是前面所提到的，没有对传入的file文件格式做判断 访问js.axd?path=/web.config时，居然将我的web.config文件内容原样读取出来 继续访问js.axd?path=app_data/users.xml，结果同上，将这个xml文件的内容一行不漏地读取了，而该文件中存储的正是帐户信息！！ 修补方法： 在private static string RetrieveLocalScript(string file)方法及private static string RetrieveRemoteScript(string file)方法中添加以下代码： //判断是不是请求.js文件，如果不是则抛出安全性异常。 if (!file.EndsWith(&#34;.js&#34;, StringComparison.OrdinalIgnoreCase)) &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; throw new System.Security.SecurityException(&#34;No access&#34;); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } 再访问上述地址时： &#160; &#160; 问题基本得到修复，官方也就此bug发布了更新版本http://www.dotnetblogengine.net/post/Critical-Security-Patch-Available.aspx 使用dotnetblogengine的朋友一定要打此补丁，否则欲哭无泪了 在此，谢谢给我邮件的朋友，他的blog地址： http://blog.119797.com/]]></description>
			<content:encoded><![CDATA[<p>在gmail的垃圾邮件里找到一封标题为《网站有漏洞哦》的邮件，好奇地打开邮件，内容是：</p>
<p>详细的参考：<br />
<a href="http://blog.119797.com/post/BlogEngine-fix-js-Download-bug.aspx" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">http://blog.119797.com/post<wbr></wbr>/BlogEngine-fix-js-Download<wbr></wbr>-bug.aspx</a><br clear="all" /><br />
<span class="sg"><br />
&#8211; <br />
by benben <br />
 <img src='http://yibin.us/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </span></p>
<p><span class="sg">由于涉及到链接，不敢用ie，用firefox打开一看，是一篇名为</span><a target="_blank" href="http://blog.119797.com/post/BlogEngine-fix-js-Download-bug.aspx">BlogEngine.NET js.axd 模块漏洞及修复</a>的文章，往下一看，果然在js.axd文件有致命的bug，该bug可以让攻击者拿到用户名及密码，有了这些，等于完全操纵了你的blog程序，可怕！</p>
<p>Bug分析：</p>
<p>js.axd文件是一个实现了IHttpHandler接口的处理文件，它的作用是将指定的js文件进行压缩与缓存，该文件需要传递一个path参数，如：js.axd?path=xxx.js，js.axd就会将xxx.js文件中的空白去掉以减小js文件的体积。</p>
<p>部分方法：</p>
<p>&lt;/p&gt;<br />
&lt;p&gt;private static string RetrieveLocalScript(string file)&lt;br /&gt;<br />
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;<br />
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; string path = HttpContext.Current.Server.MapPath(file);&lt;br /&gt;<br />
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; string script = null;&lt;br /&gt;<br />
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; using (StreamReader reader = new StreamReader(path))&lt;br /&gt;<br />
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;<br />
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; script = reader.ReadToEnd();&lt;br /&gt;<br />
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; HttpContext.Current.Cache.Insert(file, script, new CacheDependency(path));&lt;br /&gt;<br />
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;<br />
&lt;br /&gt;<br />
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return script;&lt;br /&gt;<br />
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;<br />
&lt;p&gt;</p>
<p>但这里出现的bug就是前面所提到的，没有对传入的file文件格式做判断</p>
<p>访问js.axd?path=/web.config时，居然将我的web.config文件内容原样读取出来</p>
<p>继续访问js.axd?path=app_data/users.xml，结果同上，将这个xml文件的内容一行不漏地读取了，而该文件中存储的正是帐户信息！！</p>
<p>修补方法：</p>
<p>在private static string RetrieveLocalScript(string file)方法及private static string RetrieveRemoteScript(string file)方法中添加以下代码：</p>
<p>//判断是不是请求.js文件，如果不是则抛出安全性异常。</p>
<p>if (!file.EndsWith(&quot;.js&quot;, StringComparison.OrdinalIgnoreCase))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new System.Security.SecurityException(&quot;No access&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>再访问上述地址时：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><img alt="" src="http//:yibin.us/image.axd?picture=20080415/2008-04-15_193835.png" /></p>
<p>问题基本得到修复，官方也就此bug发布了更新版本http://www.dotnetblogengine.net/post/Critical-Security-Patch-Available.aspx</p>
<p>使用dotnetblogengine的朋友一定要打此补丁，否则欲哭无泪了</p>
<p>在此，谢谢给我邮件的朋友，他的blog地址：</p>
<p>http://blog.119797.com/</p>
]]></content:encoded>
			<wfw:commentRss>http://yibin.us/archives/5932/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>[原创]BlogEngine.Net插件MP3播放器</title>
		<link>http://yibin.us/archives/5870</link>
		<comments>http://yibin.us/archives/5870#comments</comments>
		<pubDate>Fri, 28 Dec 2007 17:37:00 +0000</pubDate>
		<dc:creator>幻想曲</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[blogengine]]></category>

		<guid isPermaLink="false">http://yibin.us/?p=5870</guid>
		<description><![CDATA[发现blogengine.net的插件制作还是比较简单的，因自己喜欢在blog里帖一些音乐文件 所以，参考其它插件的制作方法，制作了该插件，显示效果见这里： [mp3:http://mrbo.net/mp3/kanon.mp3] 使用方法： 将附件中的mp3Player.cs文件放入blogengine.net\app_code\Extensions下 将mp3目录复制到blog根目录下，当然，你可以修改源代码来改变目录地址。 [mp3:文件地址]即可 mp3player.rar (9.10 kb)]]></description>
			<content:encoded><![CDATA[<p>发现blogengine.net的插件制作还是比较简单的，因自己喜欢在blog里帖一些音乐文件<br />
所以，参考其它插件的制作方法，制作了该插件，显示效果见这里：<br />
[mp3:http://mrbo.net/mp3/kanon.mp3]</p>
<p>使用方法：<br />
将附件中的mp3Player.cs文件放入blogengine.net\app_code\Extensions下<br />
将mp3目录复制到blog根目录下，当然，你可以修改源代码来改变目录地址。<br />
[mp3:文件地址]即可</p>
<p><a href="http://yibin.us/wp-content/uploads/20071228/mp3player.rar">mp3player.rar (9.10 kb)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://yibin.us/archives/5870/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

