闲来无事,突发奇想:利用局域网里的动态IP到底能不能建立一个POP3/SMTP邮件服务器呢?

于是,初步构思了一下:

(以下所说外网即指广域网/公网,内网即指局域网)

1.申请一个域名abc.com(实际过程中并不是此域名);

2.进入abc.com域名控制面板,设置该域名的A记录、MX记录为111.77.221.89(即局域网中路由器获取到的动态IP地址);

3.进入路由器WEB管理页面http://192.168.1.1/,输入用户名和密码登录成功。在“虚拟服务器”页面中添加映射

ID  服务端口    IP地址  协议 状态
1    80   192.168.1.9  TCP   生效
2    110   192.168.1.9  TCP   生效
3    25   192.168.1.9  TCP   生效
4    21   192.168.1.9  TCP   生效

其中,192.168.1.9即为本机在内网中分配的地址,此IP是固定设置的,不是路由器动态分配的。

通过端口映射,外网访问路由器IP 111.77.221.89 时,对指定的80/110/25/21四个端口的访问将直接转向到内网中IP为192.168.1.9的那台电脑,即本机。其中110和25两个端口是POP3/SMTP服务所需要的。

4.在本机windows 2003企业版系统中安装POP3/SMTP服务组件。具体步骤如下:

4.1 ‘开始’--‘设置’--‘控制面板’--‘添加或删除程序’--‘添加/删除Windows组件’,在弹出的窗口中勾选‘电子邮件服务’、‘应用程序服务器’项中的‘ASP.NET’和‘Internet 信息服务(IIS)’,然后点击‘下一步’进行安装。期间可能提示浏览安装源,放入WIN2003安装光盘即可,事先就把光盘放入光驱就不会弹出这个提示,安装更快些。

4.2 ‘开始’--‘程序’--‘管理工具’--‘POP3服务’,在管理器的左边列表中可以看到本机的计算机名称,点击并选中该名称,右边的窗口中有四个链接。点击‘新域’,在‘添加域’窗口中输入abc.com,然后‘确定’完成域的添加。

4.3 紧接上一步,点击并选中刚刚添加的域abc.com,右边的窗口中有三个链接。点击‘添加邮箱’,在弹出的窗口中输入邮箱名cs1和密码123,并保持‘为此邮箱创建相关联的用户’为勾选状态,然后‘确定’完成邮箱的添加。重复此步骤添加另一个邮箱,名为cs2。

4.4 ‘开始’--‘程序’--‘管理工具’--‘Internet 信息服务(IIS)管理器’,在管理器左边列表的‘默认SMTP虚拟服务器’上点击鼠标右键,选择‘属性’项。在属性对话窗口中选择‘访问’选项卡,并点击访问控制栏中的‘身份验证’,去掉‘匿名访问’前的勾,然后勾选最下面一项‘集成Windows身份验证’(第二项‘基本身份验证’勾选与不勾选我都试过,没有发现有什么区别),然后‘确定’完成SMTP虚拟服务器的配置。

5. 经过以上的操作后,POP3/SMTP邮件服务器就搭建完毕了。接着就可以进入测试阶段。

5.1 通过cs1邮箱发送邮件给cs2邮箱。

启动outlook express(用其他的邮件客户端也一样),分别添加cs1和cs2帐户,配置如下:

POP服务器:111.77.221.89

SMTP服务器:111.77.221.89

用户名:cs1

密码:123

其他设置:确保‘我的发送服务器(SMTP)要求验证’项为勾选状态。

然后,创建一封邮件,收件人为cs2@abc.com,标题和内容随便输入一些字母或数字均可,点击‘发送’。

此时切换到cs2邮箱帐户(Outlook Express中需要切换标识,其他客户端可同时使用多个帐户,无需切换)点击‘发送/接收’,即可收到刚刚由cs1发出的邮件。

如果能收发成功,说明通过动态IP和abc.com域名在内网中发送邮件已经没有问题。

5.2 通过cs1邮箱发送邮件给abc@gmail邮箱(实际过程中名称不同)

登录abc@gmail.com查收邮件,如果能收到刚刚由cs1发出的邮件,说明通过动态IP和abc.com域名从内网中发送邮件到外网已经也没有问题。

然后,直接回复邮件给cs1@abc.com。在Outlook Express切换到本机的cs1邮箱帐户,点击‘发送/接收’,如果能收到abc@gmail.com回复的邮件,说明也能收到外网的邮件。

 

以上内容是我根据自己前几日的实际操作写的,确实能与内网、外网互发邮件,而且速度很快。

但今天开机再试,问题来了。内网可以互发成功,外网的邮件却不行了。使用不同的外网邮箱测试,发送到外网的邮件全被退回,从退回的信息来看,并不是到达对方才退回的,而是本机的SMTP服务退回的。也就是说根本没发出去!

我仔细检查了路由器的动态IP,还是之前的IP,没有改变。到底是什么变了呢???百思不得其解。若有哪位仁兄明白,不妨相告。技术的东西需要探讨,一起进步,中国的技术才有希望。

posted @ 2010-10-06 12:30 Neville.Liu 阅读(1398) 评论(0) 编辑

    上篇随笔简单介绍了DXperience是什么,并给出了一个类似“Hello World”的例子。如果没有看过上篇请点击这里查看《从这里开始,学习DXperience 》。

    我看到评论中有朋友提到了“皮肤”,也就是常说的软件UI方面的内容。那么,我在这里也写个例子,简单的说明一下。看完这个例子后,大家就会明白,所谓“皮肤”的确只是DXperience非常小的一个部分,或者说只是一个功能点。

    接着上篇的内容,先把Program.cs和frmMain.cs准备好。

    1.从工具箱中拖一个DevExpress.XtraEditors.ComboBoxEdit控件到frmMain.cs窗体中。ComboBoxEdit控件在工具箱的位置如下图所示:

    2.为ComboBoxEdit控件添加SelectedIndexChanged事件的方法,实现ComboBoxEdit控件选择项改变后,改变窗体默认皮肤的功能。代码如下:

Code

    3.添加frmMain.cs窗体Load事件的方法,实现frmMain.cs窗体加载后,初始化ComboBoxEdit控件选项的功能。代码如下:

Code

    3.按“F5”启动调试,即可看到实际的效果。如下图所示:

    可以在皮肤样式的下拉选项中选择不同的项来查看变化(XtraTabPage控件不是本文的重点,所以上文中没有提到,大家可以不用理会)。

posted @ 2009-11-17 11:24 Neville.Liu 阅读(616) 评论(2) 编辑

    用过DXperience之后,我发现这是个不错的东东。可能有人要问了,DXperience是什么?简单的说,就是开发软件用的界面库,支持VB和C#语言,至于其它语言我没关注过。如果还有人问界面库又是什么?那就顺便也说一下。界面库对于一个软件的开发来说,不是必要的,它就像一个女人的化妆包,能使我们的软件外观看起来更漂亮、更专业(客户说的,借用一下)。

    好的界面库可以为我们在软件的外观设计上省下不少的时间和精力。当然,好东西不是免费的——毕竟制作它的公司还有一大把人需要吃饭。虽然DXperience已经设计得与系统自带的控件大体上接近,但想用好它也不是一朝一夕的事情。

    废话不再多说,现在就开始记下自己学习的过程。

    我安装的是DXperience 8.3.4版本和VS2008(SP1)。(不要问我有关下载、安装和破解之类的问题,我确定你有办法搜索到。)

1.新建一个Windows窗体应用程序的解决方案,名称为WindowsFormsApplication1。

2.删除VS自动新建的Form1.cs窗体,因为这个窗体是默认的Windows窗体。

3.添加新建项。在添加新项对话窗口中选择DevExpress Formv8.3,名称设置为frmMain.cs,点击添加按钮即可。

4.编辑Program.cs文件,代码如下:

Code

注意15行和16行,原则上是要加上这两句的。不过我注释掉后也没有发现有什么不一样。其中的21行设置了工程中窗体的默认皮肤的样式。

5.添加控件。其实完成以上几步之后,按F5运行就可以看到一些效果了。在frmMain.cs窗体上添加一些控件,比如TextEditor等可以更明显的看出使用了界面库之后的不同效果。

6.生成解决方案。这一步不用我多说,相信大家都知道要怎么做。

    怎么样?看到效果了吧。今天先说到这里了,欢迎有兴趣的朋友一起交流。

posted @ 2009-11-14 17:29 Neville.Liu 阅读(1438) 评论(11) 编辑

    刚安装完VS2008,碰巧打开一个CHM帮助文档,看不到网页内容,我就急了,第一个反应就是VS2008引起的,因为昨天我还看过这个文档,当时是正常的。可是,总不至于让我把VS2008卸载了吧?立即打开GOOGLE搜索相关的网页,结果中大部分说到的是文件属性里的安全选项卡中的“解除锁定”。其实这一招我早就知道,与今天见到的情况完全不一样,我在这个CHM文件上点击右键,选择属性,弹出对话框,根本没有“解除锁定”这个按钮。于是,再搜……

    终于在博客园一位老兄的帖子中找到了答案(http://www.cnblogs.com/vgis/articles/985953.html),这才想起我昨晚整理资料时把文件夹重命名成了C#,我遇到的情况和他当时的情况是一样的。不只是他想不明白,连我都有些疑惑,为什么CHM文件置于带#的目录里就显示不正常呢?

    现在想来,也许CHM的网页在显示时要读取本地路径,也就是说原来显示为“d:\abc\u.htm”的网页现在的路径变成了“d:\abc#\u.htm”,于是就认为#后面的是锚链接,实际显示的是“d:\abc\index.htm”或“d:\abc\”,也就是abc目录里的默认页。也不知道我的推断是不是正确,呵呵,谁知道呢?

posted @ 2008-11-04 09:31 Neville.Liu 阅读(2678) 评论(3) 编辑
摘要
缺省情况下,ASP.NET应用程序以本机的ASPNET帐号运行,该帐号属于普通用户组,权限受到一定的限制,以保障ASP.NET应用程序运行的安全。但是有时需要某个ASP.NET应用程序或者程序中的某段代码执行需要特定权限的操作,比如某个文件的存取,这时就需要给该程序或相应的某段代码赋予某个帐号的权限以执行该操作,这种方法称之为身份模拟(Impersonation)。本文介绍了在ASP.NET应用程序中使用身份模拟的几种方法,并比较了它们各自适用的范围。
在阅读本文之前,建议您先阅读文章:《ASP .NET 中的身份验证:.NET 安全性指导》 以便对ASP.NET的安全控制有一个总体的了解。

目录
  • ASP.NET中的身份模拟
  • 模拟IIS认证帐号
  • 在某个ASP.NET应用程序中模拟指定的用户帐号
  • 在代码中模拟IIS认证帐号
  • 在代码中模拟指定的用户帐号
  • 更多信息

ASP.NET中的身份模拟
ASP.NET 通过使用身份验证提供程序来实现身份验证,一般情况下,ASP.NET的身份验证提供程序包括表单身份验证、Windows身份验证和Passport身份验证3种。当通过身份验证后,ASP.NET会检查是否启用身份模拟。如果启用,ASP .NET 应用程序使用客户端标识以客户端的身份有选择地执行。否则,ASP.NET应用程序使用本机身份标识运行(一般使用本机的ASPNET帐号),具体流程如下图所示:

在ASP.NET应用程序中使用身份模拟一般用于资源访问控制,主要有如下几种方法:
  • 模拟IIS认证帐号
  • 在某个ASP.NET应用程序中模拟指定的用户帐号
  • 在代码中模拟IIS认证帐号
  • 在代码中模拟指定的用户帐号

模拟IIS认证帐号
这是最简单的一种方法,使用经过IIS认证的帐号执行应用程序。您需要在Web.config文件中添加<identity>标记,并将impersonate属性设置为true:
<identity impersonate="true" />
在这种情况下,用户身份的认证交给IIS来进行。当允许匿名登录时,IIS将一个匿名登录使用的标识(缺省情况下是IUSR_MACHINENAME)交给ASP.NET应用程序。当不允许匿名登录时,IIS将认证过的身份标识传递给ASP.NET应用程序。ASP.NET的具体访问权限由该账号的权限决定。

模拟指定的用户帐号
当ASP.NET应用程序需要以某个特定的用户帐号执行,可以在Web.config文件的<identity>标记中指定具体的用户帐号:
<identity impersonate="true" userName="accountname" password="password" />
这时该ASP.NET应用程序的所有页面的所有请求都将以指定的用户帐号权限执行。

在代码中模拟IIS认证帐号
在代码中使用身份模拟更加灵活,可以在指定的代码段中使用身份模拟,在该代码段之外恢复使用ASPNET本机帐号。该方法要求必须使用Windows的认证身份标识。下面的例子在代码中模拟IIS认证帐号:
Visual Basic .NET
Dim impersonationContext As System.Security.Principal.WindowsImpersonationContext
Dim currentWindowsIdentity As System.Security.Principal.WindowsIdentity
currentWindowsIdentity = CType(User.Identity, System.Security.Principal.WindowsIdentity)
impersonationContext = currentWindowsIdentity.Impersonate()
'Insert your code that runs under the security context of the authenticating user here.
impersonationContext.Undo()
Visual C# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
//Insert your code that runs under the security context of the authenticating user here.
impersonationContext.Undo();

在代码中模拟指定的用户帐号
下面的例子在代码中模拟指定的用户帐号:
Visual Basic .NET
<%@ Page Language="VB" %>
<%@ Import Namespace = "System.Web" %>
<%@ Import Namespace = "System.Web.Security" %>
<%@ Import Namespace = "System.Security.Principal" %>
<%@ Import Namespace = "System.Runtime.InteropServices" %>
<script runat=server>
Dim LOGON32_LOGON_INTERACTIVE As Integer  = 2
Dim LOGON32_PROVIDER_DEFAULT As Integer = 0
Dim impersonationContext As WindowsImpersonationContext
Declare Auto Function LogonUser Lib "advapi32.dll" (ByVal lpszUsername As String, _
ByVal lpszDomain As String, _
ByVal lpszPassword As String, _
ByVal dwLogonType As Integer, _
ByVal dwLogonProvider As Integer, _
ByRef phToken As IntPtr) As Integer
Declare Auto Function DuplicateToken Lib "advapi32.dll"(ByVal ExistingTokenHandle As IntPtr, _
ImpersonationLevel As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Integer
Public Sub Page_Load(s As Object, e As EventArgs)
If impersonateValidUser("username", "domain", "password") Then
'Insert your code that runs under the security context of a specific user here.
undoImpersonation()
Else
'Your impersonation failed. Therefore, include a fail-safe mechanism here.
End If
End Sub
Private Function impersonateValidUser(userName As String, _
domain As String, password As String) As Boolean
Dim tempWindowsIdentity As WindowsIdentity
Dim token As IntPtr
Dim tokenDuplicate As IntPtr
If LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, _
LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate)
impersonationContext = tempWindowsIdentity.Impersonate()
If impersonationContext Is Nothing Then
impersonateValidUser = False
Else
impersonateValidUser = True
End If
Else
impersonateValidUser = False
End If
Else
impersonateValidUser = False
End If
End Function
Private Sub undoImpersonation()
impersonationContext.Undo()
End Sub
</script>
Visual C# .NET
<%@ Page Language="C#"%>
<%@ Import Namespace = "System.Web" %>
<%@ Import Namespace = "System.Web.Security" %>
<%@ Import Namespace = "System.Security.Principal" %>
<%@ Import Namespace = "System.Runtime.InteropServices" %>
<script runat=server>
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext impersonationContext;
[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
public static extern int LogonUser(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto, SetLastError=true)]
public extern static int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
public void Page_Load(Object s, EventArgs e)
{
if(impersonateValidUser("username", "domain", "password"))
{
//Insert your code that runs under the security context of a specific user here.
undoImpersonation();
}
else
{
//Your impersonation failed. Therefore, include a fail-safe mechanism here.
}
}
private bool impersonateValidUser(String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if(LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
return true;
else
return false;
}
else
return false;
}
else
return false;
}
private void undoImpersonation()
{
impersonationContext.Undo();
}
</script>
下面介绍ASP.NET应用程序中使用身份模拟的一个简单应用。例如有一个ASP.NET应用程序要检查服务器端某个文件是否存在,相应的程序代码为:
bool a = File.Exists("D:\\Share\\test.txt");
缺省情况下该ASP.NET应用程序以ASPNET帐号运行。为了安全起见,ASPNET这个帐号并没有服务器端D:\Share\这个目录的访问权限。在不使用身份模拟的情况下,由于ASP.NET应用程序不具有访问该目录的权限,无论文件是否存在,File.Exists的返回值将永远是false。为了解决这个问题,可以另建一个用户帐号:FileExist,并赋予该帐号D:\Share\目录的访问权限。然后在该应用程序的Web.config文件的<identity>标记中指定具体的用户帐号:
<identity impersonate="true" userName="FileExist" password="password" />
来执行该程序。

更多信息
请访问以下链接获取更多信息:
1. INFO: Implementing Impersonation in an ASP.NET Application
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158&SD=MSKB
2. INFO: ASP.NET Security Overview
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306590
3. ASP.NET Web Application Security
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconaspnetwebapplicationsecurity.asp

作者:黄雪斌
 
转至:http://www.microsoft.com/china/community/program/originalarticles/techdoc/impersonation.mspx
posted @ 2008-08-12 12:59 Neville.Liu 阅读(116) 评论(1) 编辑
摘要: 在 VS 2008中,我们就开发人员所关心的一些常见的使用场景在性能上作了很大的改进.我们对新的产品功能以及现有的产品功能都设置了明确的性能指标。 例如,对于新的 LINQ,我们设置的性能目标是: 对同一个查询,LINQ的性能必须显著优于SqlDataAdapter,与SqlDataReader相比也必须有竞争力;从SQL Server检索数据时,LINQ的接口必须是最轻量级的. 在我们的测试过...阅读全文
posted @ 2008-08-06 11:03 Neville.Liu 阅读(348) 评论(3) 编辑