Asp.Net Core(.net内核)

//----------------Day1----------------
一章    Web基本原理

1节
课程说明

web窗体--设计界面--加法
使用Chrome

2节
浏览器与服务器的交互

登陆如鹏网时--工具---headers--Form Data中用户名和密码
Response返回的信息
www.rupeng.com---status code 301(重定向首页)
浏览器向服务器发送请求,服务器处理之后,返回给浏览器(html)

3节
Socket原理和编写控制台浏览器代码

Socket是进行网路通讯的技术
qq用户发送的信息通过Socket把信息发送给qqServer,qqServer返回给用户
Socket原理性代码: (TCP UDP两种方式)

1、编写“控制台浏览器”
//把本机网址的html写入socket
Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);//TCP、UDP。
socket.Connect(new DnsEndPoint("127.0.0.1", 8080));//连接服务器。http协议默认的端口号是80。每个服务器软件监听一个端口(别的软件就不能监听这个端口了),发送给这个端口的数据只会被这个服务器软件接收到。
using (NetworkStream netStream = new NetworkStream(socket))//读写socket通讯数据的流
using (StreamWriter writer = new StreamWriter(netStream))
{
    writer.WriteLine("GET /index.html HTTP/1.1");//每一行指令都回车一下
    writer.WriteLine("Host: 127.0.0.1:8080");
    writer.WriteLine();//空行回车,表示指令结束
}
//从socket读取html
using (NetworkStream netStream = new NetworkStream(socket))
using (StreamReader reader = new StreamReader(netStream))
{
    string line;
    while ((line = reader.ReadLine())!=null)
    {
        Console.WriteLine(line);                    
    }
}
socket.Disconnect(false);

4节
编写"网站服务器"

//自己写的最简单的webservice
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//宿舍大妈
            serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8080));
            serverSocket.Listen(10);
            while (true)
            {
                Console.WriteLine("等着请求");
                Socket socket = serverSocket.Accept();//男女通讯通道。返回大妈给你的这个人的通讯通道
                Console.WriteLine("来了请求");
                using(NetworkStream stream = new NetworkStream(socket))
                using (StreamReader reader = new StreamReader(stream))
                {
            //读取出第一行
                    string line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        Console.WriteLine(line);
                        if (line.Length <= 0)
                        {
                            break;//遇到空行了,请求结束了不用再等了
                            //如果不break,就一直卡在ReadLine()等着浏览器发后续的数据
                        }
                    }
                }

using (NetworkStream stream = new NetworkStream(socket))
                using(StreamWriter writer = new StreamWriter(stream))
                {
                    writer.WriteLine("HTTP/1.1 200 OK");
                    writer.WriteLine();
                    writer.WriteLine("welcome to rupeng.com");
                }
                socket.Disconnect(false);
            }

5节
编写"网站服务器" 范虎请求的页面

//自己写的最简单的webservice
namespace MyWeb服务器2
{
    class Program
    {
        static void Main(string[] args)
        {
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//宿舍大妈
            serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8080));
            serverSocket.Listen(10);
            while (true)
            {
                Console.WriteLine("等着请求");
                Socket socket = serverSocket.Accept();//男女通讯通道。返回大妈给你的这个人的通讯通道
                Console.WriteLine("来了请求");
                string firstLine;
                using (NetworkStream stream = new NetworkStream(socket))
                using (StreamReader reader = new StreamReader(stream))
                {
                    firstLine = reader.ReadLine();//读取GET /1.htm HTTP/1.1
                    string line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        Console.WriteLine(line);
                        if (line.Length <= 0)
                        {
                            break;//遇到空行了,请求结束了不用再等了
                            //如果不break,就一直卡在ReadLine()等着浏览器发后续的数据
                        }
                    }
                }
               // Regex.Match(firstLine, "GET (.+) HTTP/1\\.1");
                string[] strs = firstLine.Split(' ');
                string url = strs[1];///分析出文件名1.htm

Console.WriteLine("url="+url);
                using (NetworkStream stream = new NetworkStream(socket))
                using (StreamWriter writer = new StreamWriter(stream))
                {
                    string filePath = @"F:\快盘\NextBig\NET课程\ASP.net\myweb服务器" + url;
                    Console.WriteLine("filePath=" + filePath);
                    if (File.Exists(filePath))
                    {
                        writer.WriteLine("HTTP/1.1 200 OK");
                        writer.WriteLine();
                        string html =
                            File.ReadAllText(filePath);
                        Console.WriteLine(html);
                        writer.Write(html);
                    }
                    else
                    {
                        writer.WriteLine("HTTP/1.1 404 NOT FOUND");
                        writer.WriteLine();
                        writer.Write("没有找到");
                    }
                }
                socket.Disconnect(false);
            }
        }
    }
}

6节
服务器动态的计算

add?i=1&j=2
//把add?i=1&j=2转换为字典
ParseQueryString(string str)
//分割后获得name和value ,及i和1,加入返回dictonary中

//练习:login?username='admin'&password='123'

namespace MyWeb服务器3
{
    class Program
    {
        static void Main(string[] args)
        {
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//宿舍大妈
            serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8080));
            serverSocket.Listen(10);
            while (true)
            {
                Console.WriteLine("等着请求");
                Socket socket = serverSocket.Accept();//男女通讯通道。返回大妈给你的这个人的通讯通道
                Console.WriteLine("来了请求");
                string firstLine;
                using (NetworkStream stream = new NetworkStream(socket))
                using (StreamReader reader = new StreamReader(stream))
                {
                    firstLine = reader.ReadLine();//读取GET /1.htm HTTP/1.1
                    string line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        Console.WriteLine(line);
                        if (line.Length <= 0)
                        {
                            break;//遇到空行了,请求结束了不用再等了
                            //如果不break,就一直卡在ReadLine()等着浏览器发后续的数据
                        }
                    }
                }
                // Regex.Match(firstLine, "GET (.+) HTTP/1\\.1");
                string[] strs = firstLine.Split(' ');
                string url = strs[1];///分析出文件名add?i=1&j=2
                string[] strs2 = url.Split('?');
                string fileAction = strs[0];//add
                string qs = strs2[1];
                Dictionary<string, string> dict = ParseQueryString(qs);
                int i = Convert.ToInt32(dict["i"]);
                int j = Convert.ToInt32(dict["j"]);

using (NetworkStream stream = new NetworkStream(socket))
                using (StreamWriter writer = new StreamWriter(stream))
                {
                    writer.WriteLine("HTTP/1.1 200 OK");
                    writer.WriteLine();
                    writer.WriteLine(i+j);
                }
                socket.Disconnect(false);
            }
        }

/// <summary>
        /// 把i=1&j=2&w=aaa转换为一个Dictionary
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        static Dictionary<string, string> ParseQueryString(string qs)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();
            string[] strs = qs.Split('&');
            foreach (string str in strs)
            {
                string[] kv = str.Split('=');
                string name = kv[0];
                string value = kv[1];
                dict.Add(name, value);
            }
            return dict;
        }
    }
}

7节

服务器知道浏览器什么时候关闭吗?
除非浏览器请求,否则服务器无法主动向浏览器发送数据

8节
web服务器和asp.net服务器能做什么

自己写webservice: 太累 并发性 安全性
现成的webservice: Apache Ngix IIS
先用微软的Cassini,然后才用IIS
//请求的处理,报文的处理,参数的处理,用现成的Web服务器

新建Web--一旦处理程序

9节
HttpHandler(ashx)

ashx下面有个ashx.cs就是C#代码,ashx是微软傻瓜化的结果
当用户访问test1.ashx时,服务器调用ashx.cs中test1的ProcessRequest方法

项目--属性--Web--服务器--默认勾上了IIS Express(IIS简化版) //推荐使用IIS Web服务器--报错目录--可以直接使用地址
项目--属性--Web--特定页--把页面地址写入进去
选择一个浏览器--选择浏览器的安装目录

调试时不能修改
虽然停止调试了,只要IIS还在运行的,改了代码后重新生成,就可以直接刷新访问,html不用生成也可以访问

10节

context.Response.ContentType = "text/html";
            string username = context.Request["username"];
            string password = context.Request["password"];
            context.Response.Write("<html><head></head><body>");
            if (username == "admin" && password == "123")
            {
                context.Response.Write("<h1>欢迎光临</h1>");
            }
            else
            {
                context.Response.Write("<img src='3.jpg'/>");
            }

11节
表单提交

重复的name也会被提交,没有name就不会提交给服务器
input textarea select 只有这3中属性的value值才能被提交给web服务器
submit比较特殊,只有被点击的submit的name和value才会提交给服务器,其他的不会提交给服务器
对于select是选中的那个select才提交给服务器

//----------------Day2-------------
二章    一般处理程序

12节
http协议

Restart、Reinstall、Reboot
favicon.ico 就是一个默认的图标,浏览器每次访问,服务器都尝试去访问这个网页,如果存在就显示这个图标
后缀名是可以骗人的
浏览器不知道服务器内部发生了什么,只接收结果,返回什么就显示什么

连接Connection :浏览器与服务器之间传输数据的通道。http协议在请求期间还是支持保持连接Keep-Alice的,但是结束还是会断开连接
请求Request
处理Process
响应Response

13节

请求

浏览器就是骗人的: 浏览器发出的所有请求都是可以被伪造的,一定不能信任浏览器的请求
User-Agent:UA 用户代理,代理用户发出http请求的,就是一些当前浏览器信息
Referer:这个请求来自于那个网页
Accept-Encoding:服务器支持什么压缩算法
Accept-Language:该浏览器支持哪种语言

响应
服务器也是可以骗人的,可以欺骗黑客
HTTP/1.0 200 OK  //200返回的状态码,如果为404就是not found //500为internal server error //跳出"黄页",可以根据报错信息,找到出现错误的异常
Content-Type: 服务器返回的是什么类型的数据 (后缀名是可以造假的) charset=utf-8;报文体采用的编码
Accept-Rangge: 服务器是否支持断点续传
Server: 哪种服务器
Date:返回日期
Content-Length:内容长度

HTTP/1.0 302 Found //302重定向到Localing的页面
context.Response.Redirect(); //重定向

HTTP/1.0 304 Not Modified // 表示没有修改,从缓存取,没有报文体
If-Modifed-Since:保存的修改日期,再次访问表示没有修改,如果没有修改就直接重缓存中加载数据的

状态码 -->
2XX:表示没问题
3XX: 需要浏览器干点啥
4XX:浏览器提交的数据有问题(客服端的访问未授权)
5XX: 服务器错误

响应码:
“200” : OK;
“302” : Found 暂时转移,用于重定向, Response.Redirect()会让浏览器再请求一次重定向的地址,重定向的请求是Get方式;
"404" : Not Found 未找到。
500 服务器错误(一般服务器出现异常),通过报错信息找出异常的点。
403:客户端访问未被授权。
304(服务器把文件的修改日期通过Last-Modified返回给浏览器,浏览器缓存这个文件,下次向服务器请求这个文件的时候,通过If-Modified-Since问服务器说“我本地的文件的修改日期是。。。”,服务器端如果发现文件还是那个文件,则告诉浏览器(304 Not Modified)文件没修改,还用本地的吧。ctrl+f5)。
2xx:没问题;3xx代表浏览器需要干点啥;4***浏览器的问题;5xx服务器错误

14节
Get和Post的区别

get把数据放在地址栏,post把数据放到报文体中,提交大数据,传密码安全
对于post请求只要在地址栏中输入一个网址回车就是get请求;刷新,重新发出post请求,部分浏览器会提示是否重新提交
反编译器搜索httpRequest这个类

15节
ASP.Net内核几大对象HttpContext;
context.Request对象

请求参数都是字符串,因为http协议是string
只要浏览器没提交,服务器就获取不了
//HttpContext和当前线程相关的对象,在子线程中拿不到这个对象

//1
void Test(HttpContext context)
{
    if() context.Request["a"]不存在
}

//2
void Test()
{
 HttpContext context=HttpContext.current;
 if() context.Request["a"]不存在
}

//3 post
string name=context.Request.Form["name"]; //只获得通过报文体传输的参数

//4 get
string name=context.Request.QueryString["name"]; //只获取通过get方式获得参数

//5
context.Response.Write("'+context.Request.Browser.Browser+'\n"); //返回打印浏览器的浏览器名 Platform  Version
i < context.Request.Headers.AllKeys.Length
string k=context.Request.Headers.AllKeys[i];
string v=context.Request.Headers[k];

namespace Web1
{
    /// <summary>
    /// RequestTest1 的摘要说明
    /// </summary>
    public class RequestTest1 : IHttpHandler
    {

public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            //context.Request.Form["name"]获得通过报文体传输的参数
           // string name = context.Request.Form["name"];
            //string age = context.Request.Form["age"];//拿到的都是String,Convert.ToInt32()

//context.Request.QueryString获得GET方式中“GET /Test.ashx?id=5 HTTP/1.1”中的
            //"id=5"值
            //string name = context.Request.QueryString["name"];
            //string age = context.Request.QueryString["age"];

//context.Request["name"]无论是Get还是Post都能获得
           // string name = context.Request["name"];//[""]索引器
           // string age = context.Request["age"];
            context.Response.Write("" + context.Request.Browser.Browser+ "\n");
            context.Response.Write("" + context.Request.Browser.Platform + "\n");
            context.Response.Write("" + context.Request.Browser.Version + "\n");

context.Response.Write("------------------------\n");
            for (int i = 0; i < context.Request.Headers.AllKeys.Length; i++)//Request.Headers请求报文头
            {
                string key = context.Request.Headers.AllKeys[i];
                string value = context.Request.Headers[key];
                context.Response.Write(key+"="+value+"\n");
            }
            context.Response.Write("------------------------\n");

context.Response.Write(context.Request.HttpMethod + "\n");
            //context.Response.Write(context.Request.InputStream);//请求报文体的流
            context.Response.Write(context.Request.Path + "\n");
            context.Response.Write(context.Request.QueryString + "\n");
            context.Response.Write(context.Request.PhysicalPath + "\n");//被请求的文件的服务器上的物理路径
            context.Response.Write(context.Request.UserAgent + "\n");
            context.Response.Write(context.Request.UserHostAddress + "\n");//客户端的IP地址
            context.Response.Write(context.Request.UrlReferrer + "\n");
            context.Response.Write(String.Join(",",context.Request.UserLanguages) + "\n");//浏览器支持什么语言
        }

public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

16节
context.Response对象

ContentType :
OutputStream :图片,二进制输出流
Redirect:重定向
//性能并不是唯一追求的指标

if(username为nullOrEmpty)
{
    context.Response.Write("用户名为空");
    //return;
    context.Response.End(); //终止httpHandler的执行  //因为它抛了一个异常,所以没有继续执行,可以用try catch抓住这个异常,因为异常处理效率低,所以尽量不用response.end()
}

void Test()
{
    HttpContext.Current.Respnse.Write("数据库插入失败");
    //return; //只是终止Test()的执行
    HttpContext.Current.Response.End();
}

End()将当前所有缓冲的输出发送到客户端,停止该页的执行。通过对End()进行try,发现是是抛出了异常。所以End()之后的代码就不会执行了。

17节
context.Server对象

Server.Transfer:控制权的转移
Server.Mapth:获得绝对路径
Server.HtmlEncode:HTML编码解码
Server.UrlEncode:url编码解码

context.Server.Transfer("sayhello?name=admin&age=18"); //有错,以后讲

FileInfo fi=new FileInfo(@"E:\s1.jpg"); //永远不用相对路劲,容易进坑
context.Server.MapPath("~/3.jpg"); //获得文件的绝对路径,~表示网站的根目录
string csCode="helllo List<T> list=new List<T>()";
context.Server.HtmlEncode(csCode);
context.Server.HtmlDecode(csCode);
string str="如鹏 12什么么";
context.Server.UrlEncode(str); //转换为url编码

Server是一个HttpServerUtility类型的对象,不是一个类名
MapPath:MapPath("~/a.htm")将虚拟路径(~代表项目根目录)转换为磁盘上的绝对路径,操作项目中的文件使用。
HtmlEncode、 HtmlDecode:HTML编码解码。Encode为的是把特殊字符转义显示,举例子:"< 如鹏+网  rupeng.com>"
UrlEncode、 UrlDecode:url编码解码。汉字、特殊字符(空格、尖括号)等通过Url传递的时候要编码,举例子“"<如鹏+网  rupeng.com>”

18节

ContentType = "image/jpg";
//浏览器是不知道服务器上有3.jpg的存在的,浏览器只是发请求,显示图片
//把文件流的数据拷贝到outputstream输出流

//输出一个动态创建的图片
//图片中显示访问者浏览器信息
//把名字写入泡妞证
//生成验证码,动态生成一200*50的图片,显示一个随机的4位数

//context.Response.ContentType = "image/jpeg";//image/gif image/png
    
    //1
            /*
            string filepath = context.Server.MapPath("~/3.jpg");
            //浏览器是不知道服务器上有3.jpg的存在的,浏览器只是发请求,接收请求,显示图片
            //别的一概不知
            using (Stream inStream = File.OpenRead(filepath))//new FileStream(...);
            {
                inStream.CopyTo(context.Response.OutputStream);
            }*/

//2
            /*
            using (Bitmap bmp = new Bitmap(500, 500))//创建一个尺寸为500*500的内存图片
            using (Graphics g = Graphics.FromImage(bmp))//得到图片的画布
            {
                g.DrawString("如鹏网万岁", new Font(FontFamily.GenericSerif, 30), Brushes.Red, 100, 100);//Font应该被释放
                g.DrawEllipse(Pens.Blue, 100, 100, 100, 100);
                //bmp.Save(@"d:\1.jpg", ImageFormat.Jpeg);
                //直接保存到网页输出流中
                bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);
            } */
    //3
        // string name = context.Request["name"];
            /*
            using (Bitmap bmp = new Bitmap(500, 500))//创建一个尺寸为500*500的内存图片
            using (Graphics g = Graphics.FromImage(bmp))//得到图片的画布
            {
                g.DrawString(name+"万岁", new Font(FontFamily.GenericSerif, 30), Brushes.Red, 100, 100);//Font应该被释放
                g.DrawEllipse(Pens.Blue, 100, 100, 100, 100);
                //bmp.Save(@"d:\1.jpg", ImageFormat.Jpeg);
                //直接保存到网页输出流中
                bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);
            }*/

/*
            context.Response.ContentType = "image/jpeg";
            using (Bitmap bmp = new Bitmap(500, 200))//创建一个尺寸为500*500的内存图片
            using (Graphics g = Graphics.FromImage(bmp))//得到图片的画布
            using (Font font = new Font(FontFamily.GenericSerif, 30))
            {
                HttpRequest request = context.Request;
                g.DrawString("IP:" + request.UserHostAddress, font, Brushes.Red, 0, 0);
                g.DrawString("浏览器:" + request.Browser.Browser + request.Browser.Version, font, Brushes.Red, 0, 50);
                g.DrawString("操作系统:" + request.Browser.Platform, font, Brushes.Red, 0, 100);
                bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);//图片保存到输出流
            }*/

context.Response.ContentType = "image/jpeg";
            string name = context.Request["name"];
            string imgFullPath = context.Server.MapPath("~/PaoNiuZheng.jpg");
            using (Image bmp = Bitmap.FromFile(imgFullPath))//读取一张已有的图片
            using (Graphics g = Graphics.FromImage(bmp))//得到图片的画布
            using (Font font1 = new Font(FontFamily.GenericSerif, 12))
            using (Font font2 = new Font(FontFamily.GenericSerif, 5))
            {
                {
                    g.DrawString(name, font1, Brushes.Black, 125, 220);//Font应该被释放
                    g.DrawString(name, font2, Brushes.Black, 309, 55);//Font应该被释放
                    bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);//图片保存到输出流
                }
            }
            //对浏览器来讲,只知道“服务器哥哥给我返回了一个image/jpeg,正文就是图片”

19节
文件下载

对于.ashx右键下载,其实是l向f发送http请求

context.Response.ContentType = "application/ms-excel";

/*
            //增加Content-Disposition是告诉浏览器,这个返回的内容是“附件形式”要给用户保存
            //filename是建议的文件名            
            context.Response.AddHeader("Content-Disposition", "attachment;filename=" +
                context.Server.UrlEncode("动态文件.txt"));    //-------------???---格式不对-----------------
            DataTable dt = SqlHelper.ExecuteQuery("select * from t_persons");
            foreach (DataRow row in dt.Rows)
            {
                context.Response.Write(row["Name"]+"!"+row["Age"]+"\r\n");
            }*/

context.Response.AddHeader("Content-Disposition", "attachment;filename=" +
                context.Server.UrlEncode("人员列表.xls"));
            IWorkbook workbook = new HSSFWorkbook() ;//new XSSFWorkbook();//xlsx
            ISheet sheet = workbook.CreateSheet("人员列表");
            DataTable dt = SqlHelper.ExecuteQuery("select * from t_persons");
            for (int i=0;i<dt.Rows.Count;i++)
            {
                IRow excelRow = sheet.CreateRow(i);
                DataRow dataRow = dt.Rows[i];
                ICell cell0 = excelRow.CreateCell(0);
                cell0.SetCellValue((string)dataRow["Name"]);

ICell cell1 = excelRow.CreateCell(1);
                cell1.SetCellValue((int)dataRow["Age"]);
            }
            workbook.Write(context.Response.OutputStream);

20节
文件上传

post
enctype="multipart/form-data"
HttpPostFile
file1.SaveAs(全路径);
//判断文件大小,不能超过1M
//根据文件后缀判断文件类型,ContentType可以伪造

context.Response.ContentType = "text/html";
            HttpPostedFile file1 = context.Request.Files["file1"];//上传的文件,可以是多个
            HttpPostedFile filehaha = context.Request.Files["filehaha"];
            string name = context.Request["name"];
            //HttpPostedFile.FileName是文件名,通过查看报文发现,FileName是浏览器提交过去的
            if (file1.ContentLength > 1024 * 1024)
            {
                context.Response.Write("文件不能超过1MB");
                return;
            }

//为什么根据ContentType判断文件类型不安全。
            //因为ContentType是浏览器提交的,是可以造假的,文件内容是病毒,filename是1.exe
            //ContentType伪造成了"image/jpeg"。
            /*
            if(file1.ContentType!="image/jpeg"&&file1.ContentType!="image/gif"
                 &&file1.ContentType!="image/png")
            {
                context.Response.Write("文件类型不允许");
                return;
            }*/
            string fileExt = Path.GetExtension(file1.FileName);
            if(fileExt!=".jpg"&&fileExt!=".gif"&&fileExt!=".png")
            {
                context.Response.Write("文件类型不允许");
                return;
            }

string localFileName = context.Server.MapPath("~/upload") + "/" + file1.FileName;
            file1.SaveAs(localFileName);//把文件保存到服务器上
            context.Response.Write(localFileName+"<br/>");
            context.Response.Write(name);
        }

//判断文件大小和类型,并在图片上画上一行字

context.Response.ContentType = "text/html";
            HttpPostedFile file1 = context.Request.Files["file1"];
            if (file1.ContentLength > 1024 * 1024)
            {
                context.Response.Write("文件不能超过1MB");
                return;
            }
            string fileExt = Path.GetExtension(file1.FileName);
            if (fileExt != ".jpg" && fileExt != ".jpeg")
            {
                context.Response.Write("只允许jpg图片");
                return;
            }
            //用户上传的文件尽量“不落地”,也就是不保存到本地,可以避免:上传文件把服务器撑爆;
            //上传非法文件造成安全性问题。
            //只能证明一段代码有漏洞,不能证明代码没有漏洞。

using (Image img = Bitmap.FromStream(file1.InputStream))//**
            {
                using (Graphics g = Graphics.FromImage(img))
                using (Font font = new Font(FontFamily.GenericSerif, 18))
                {
                    g.DrawString("如鹏网 rupeng.com", font, Brushes.Red, 0, 0);
                }

string filename = DateTime.Now.ToString("yyyyMMdd");//20150308
                img.Save(context.Server.MapPath("~/upload/" + filename + fileExt));
            }

/----------------------Day3---------------------
三章    ashx增删改查

21节
作业讲解

//Excel上传
//保存文件到yyyy\mm\dd.png中

每次return输出打印结束,都输出html结束标签
if(file1.COntentLength<=0){未上传文件};
以调试方式启动,才可以进行断点调试
不需要别人告诉结论,你试验的结果就是真理
IWrokbook workbook=WorkbookFactory.Create(file1.InputStream);
sheet.SheetName //获得sheet名
i<sheet.LastRowNum 从i=1开始
j<excelRow.LastCellNum 从j=ecelRow.FirstCellNum开始
string fileFullPath=Path.Combine(dirFullPath,file1.FileName);
if(!Directory.Exists(dirFullPath)){就创建这个文件夹}

22节
模板文件

Id Name Age Gender
//从数据库查询Person,通过html拼接,在.ashx输出信息

//html中的占位符@Name用.ashx中的值替换

public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";
        //判断id时否合法
            int id = Convert.ToInt32(context.Request["id"]);

DataTable table =
                SqlHelper.ExecuteQuery("select * from T_Persons where Id=@Id", new SqlParameter("@Id", id));
            if (table.Rows.Count <= 0)
            {                
                return;
            }
            DataRow row = table.Rows[0];
            string name = (string)row["Name"];
            int age = (int)row["age"];

string pesronViewHtmlFileName = context.Server.MapPath("~/Day3/PersonView2.txt");
            string personViewHtml = File.ReadAllText(pesronViewHtmlFileName);
            personViewHtml = personViewHtml.Replace("@name", name).Replace("@age",age.ToString());
           // personViewHtml = personViewHtml.Replace("@name", name);
            //personViewHtml = personViewHtml.Replace("@age", age.ToString());

context.Response.Write(personViewHtml);
        }

23节
通过抽象提取方法优化例子

模板优化:如果报错,输出报错信息
"{msg}" --> 占位符
封装:读取虚拟路劲下的.html文件,返回html字符串 CommonHelper.cs
封装:输出错误信息

public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";
        //判断id是否合法
            string strId = context.Request["id"];
            if (string.IsNullOrEmpty(strId))
            {
              //  string errorFileName = context.Server.MapPath("~/Day3/PersonViewError.html");
                //string errorHtml = File.ReadAllText(errorFileName);
               // string errorHtml = CommonHelper.ReadHtml("~/Day3/PersonViewError.html");
                //errorHtml = errorHtml.Replace("{msg}", "id不能为空!");
                //context.Response.Write(errorHtml);
                OutputError("id不能为空!");
                return;
            }
            int id = Convert.ToInt32(strId);

DataTable table =
                SqlHelper.ExecuteQuery("select * from T_Persons where Id=@Id", new SqlParameter("@Id", id));
            if (table.Rows.Count <= 0)
            {
               // string errorFileName = context.Server.MapPath("~/Day3/PersonViewError.html");
                //string errorHtml = File.ReadAllText(errorFileName);
              //  string errorHtml = CommonHelper.ReadHtml("~/Day3/PersonViewError.html");
                //errorHtml = errorHtml.Replace("{msg}", "id不存在!");
                //context.Response.Write(errorHtml);
                OutputError("id不存在!");
                return;
            }
            DataRow row = table.Rows[0];
            string name = (string)row["Name"];
            int age = (int)row["age"];
            //DRY:Don't Repeat YourSelf:别拷代码
            //string pesronViewHtmlFileName = context.Server.MapPath("~/Day3/PersonView2.txt");
           // string personViewHtml = File.ReadAllText(pesronViewHtmlFileName);
            string personViewHtml = CommonHelper.ReadHtml("~/Day3/PersonView2.txt");
            personViewHtml = personViewHtml.Replace("@name", name).Replace("@age",age.ToString());
           // personViewHtml = personViewHtml.Replace("@name", name);
            //personViewHtml = personViewHtml.Replace("@age", age.ToString());

context.Response.Write(personViewHtml);
        }

private void OutputError(string msg)
        {
            string errorHtml = CommonHelper.ReadHtml("~/Day3/PersonViewError.html");
            errorHtml = errorHtml.Replace("{msg}", msg);
            HttpContext.Current.Response.Write(errorHtml);
        }

24节
T_Persons列表

<table>标签中不能出现文本,但是没什么关系
<table>中{Persons}被.ashx替换
模板的好处是不用改C#代码,显示什么只需改.html就行了

//删除
删除之后重定向到列表页面,发生了2次请求   context.Response.Redirect("PersonList.ashx");//删除完成后重定向回列表页面
判断是否要删除,在js中去转义,需要在C#中加上一个 \"
 //1
 .Append("<td><td><a onclick='return confirm(\"你真的要删除吗?\")' href='PersonDelete.ashx?id=")
 .Append(row["id"]).Append("'>删除</a></td>");
 //2
 onclick=\"if(!confirm('您确定要删除吗?')){return false;}\"

25节
新增和编辑

context.Response.ContentType = "text/html";
            //PesonEditAddNew.ashx?action=addnew,新增
            //PesonEditAddNew.ahsx?action=edit&id=1
            string action = context.Request["action"];
            string html = CommonHelper.ReadHtml("~/Day3/PersonEditAddNew.html");
            if (action == "addnew")
            {
                html = html.Replace("{actionName}", "新增").Replace("{name}", "").Replace("{age}", "18")
                    .Replace("{gender}", "checked");
                context.Response.Write(html);
            }
            else if (action == "edit")
            {
                int id = Convert.ToInt32(context.Request["id"]);
                DataTable table = SqlHelper.ExecuteQuery("Select * from T_Persons where Id=@Id",
                    new SqlParameter("@Id",id));
                if (table.Rows.Count <= 0)
                {
                    CommonHelper.OutputError("没找到id="+id+"的人员");
                    return;
                }
                if (table.Rows.Count > 1)
                {
                    CommonHelper.OutputError("找到多条id=" + id + "的人员");
                    return;
                }
                DataRow row = table.Rows[0];
                string name = (string)row["name"];
                int age = (int)row["age"];
                bool gender = (bool)row["gender"];

html = html.Replace("{actionName}", "编辑").Replace("{name}", name).Replace("{age}", age.ToString())
                    .Replace("{gender}",gender?"checked":"");
                
                context.Response.Write(html);
            }
            else
            {
                CommonHelper.OutputError("action错误");
            }
        }

26节
保存

只有浏览器提交的,服务器才能知道,action是addnew还是edit必须由浏览器提交

27节
公司的增删改查(下拉列表)

T_Company( Id Name Address ManageId)
T_Boss( Id Name Age Gender)

sql语句:联合查询
//作业:学生管理系统

//班级---List

public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";
            //获得所有班级
            DataTable dtCla = SqlHelper.ExecuteQuery(@"select c.CId CId,c.CName CName,c.CClassroomNum CClassroomNum,t.TName TName
                               from T_Classes c left join T_Teachers t on c.TId=t.TId");
            if(dtCla.Rows.Count<=0)
            {
                CommonHelper.OutputErrorHtml("没有查到任何班级");
            }
            //遍历班级,拼接字符串<tr>
            StringBuilder sb = new StringBuilder();
            foreach(DataRow row in dtCla.Rows)
            {
                sb.Append("<tr><td>").Append(row["CName"]).Append("</td><td>").Append(row["CClassroomNum"]).Append("</td><td>").Append(row["TName"]).Append("</td>");
                sb.Append("<td>").Append("<a onclick=\"return confirm('您确定要删除吗?');\" href='Delete.ashx?id=").Append(row["CId"]).Append("'>删除</a></td>");
                sb.Append("<td><a href='Edit.ashx?action=edit&id=").Append(row["CId"]).Append("'>修改</a></td>").Append("</tr>");
            }
            //获得html并替换输出
            string htmlStr = CommonHelper.OutputHtml("~/Class/List.html");
            string html = htmlStr.Replace("{classes}", sb.ToString());
            context.Response.Write(html);
        }

//班级---Edit

public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";
            string save = context.Request["save"];
            string action = context.Request["action"];
            //判断直接范问还是保存
            if(string.IsNullOrEmpty(save))
            {
                //判断新增还是编辑
                if(action=="addnew")
                {
                    //获得所有的老师
                    DataTable dtTea = SqlHelper.ExecuteQuery("select * from T_Teachers");
                    StringBuilder sb = new StringBuilder();
                    foreach(DataRow row in dtTea.Rows)
                    {
                        sb.Append("<option value='").Append(row["TId"]).Append("'>").Append(row["TName"]).AppendLine("</option>");
                    }
                    //获得html并替换
                    string htmlStr = CommonHelper.OutputHtml("~/Class/Edit.html");
                    string html = htmlStr.Replace("actionName","新增").Replace("action","addnew").Replace("@CName","").Replace("@CClassroomNum","").Replace("{teachers}",sb.ToString());
                    context.Response.Write(html);
                }
                else if(action=="edit")
                {
                    //获得id
                    string idStr=context.Request["id"];
                    long id = CommonHelper.CheckStringIsLong(idStr);
                    //获得所有的老师
                    DataTable dtTea = SqlHelper.ExecuteQuery("select * from T_Teachers");
                    StringBuilder sb = new StringBuilder();
                    foreach(DataRow row in dtTea.Rows)
                    {
                        if(row["TId"].ToString()==idStr)
                        {
                            sb.Append("<option selected value='").Append(row["TId"]).Append("'>").Append(row["TName"]).AppendLine("</option>");
                        }
                        else
                        {
                            sb.Append("<option value='").Append(row["TId"]).Append("'>").Append(row["TName"]).AppendLine("</option>");
                        }
                    }
                    //获得指定id的班级
                    DataTable dtCla = SqlHelper.ExecuteQuery("select * from T_Classes where CId=@CId",
                        new SqlParameter(){ParameterName="@CId",Value=id});
                    if(dtCla.Rows.Count<=0)
                    {
                        CommonHelper.OutputErrorHtml("没有查到该id的数据:"+id);
                    }
                    else if (dtCla.Rows.Count == 1)
                    {
                        DataRow row = dtCla.Rows[0];
                        //获得html并替换
                        string htmlStr = CommonHelper.OutputHtml("~/Class/Edit.html");
                        string html = htmlStr.Replace("actionName", "编辑").Replace("action", "edit").Replace("@CId", idStr).Replace("@CName", row["CName"].ToString()).Replace("@CClassroomNum", row["CClassroomNum"].ToString()).Replace("{teachers}", sb.ToString());
                        context.Response.Write(html);
                    }
                    else
                    {
                        CommonHelper.OutputErrorHtml("存在多个id的数据:"+id);
                    }
                    
                }
                else
                {
                    CommonHelper.OutputErrorHtml("action错误:" + action);
                }
            }
            else if(save=="save") //保存-------------------------------------------------------------------------
            {
                //获得共同的项
                string cname = context.Request["CName"];
                string cclassroomNum = context.Request["CClassroomNum"];
                string tidStr = context.Request["TId"];
                long tid = CommonHelper.CheckStringIsLong(tidStr);
                //获得共同的参数
                List<SqlParameter> list = new List<SqlParameter>();
                SqlParameter[] param = {
                                           new SqlParameter("@CName",cname),
                                           new SqlParameter("@CClassroomNum",cclassroomNum),
                                           new SqlParameter(){ParameterName="@TId",Value=tid}
                                       };
                list.AddRange(param);
                //判断新增还是编辑
                int i = -1;
                if (action == "addnew")
                {
                     i = SqlHelper.ExecuteNonQuery("insert into T_Classes(CName,CClassroomNum,TId) values(@CName,@CClassroomNum,@TId)", param);
                }
                else if (action == "edit")
                {
                    //huode id
                    string cidStr = context.Request["CId"];
                    long cid = CommonHelper.CheckStringIsLong(cidStr);
                    list.Add(new SqlParameter() { ParameterName = "@CId", Value = cid });
                    i = SqlHelper.ExecuteNonQuery("update T_Classes set CName=@CName,CClassroomNum=@CClassroomNum,TId=@TId where CId=@CId", list.ToArray());
                }
                else
                {
                    CommonHelper.OutputErrorHtml("action错误:" + action);
                }
                if(i>0)
                {
                    context.Response.Redirect("~/Class/List.ashx");
                }
                else
                {
                    CommonHelper.OutputErrorHtml("操作失败");
                }
            }
            else
            {
                CommonHelper.OutputErrorHtml("save错误:" + save);
            }
        }

//班级---Delete

public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";
            string cidStr = context.Request["id"];
            long cid = CommonHelper.CheckStringIsLong(cidStr);
            //删除指定cid的班级,需要先删除指定cid的学生
            int count = (int)SqlHelper.ExecuteScalar("select COUNT(*) from T_Students where CId=@CId",
                new SqlParameter() { ParameterName = "@CId", Value = cid });
            int i = -1;
            if(count>0) //有该班级的学生
            {
                i = SqlHelper.ExecuteNonQuery("delete from T_Students where CId=@CId",
                    new SqlParameter() { ParameterName = "@CId", Value = cid });
            }
            i = SqlHelper.ExecuteNonQuery("delete from T_Classes where CId=@CId",
                new SqlParameter() { ParameterName = "@CId", Value = cid });
            if(i>0)
            {
                context.Response.Redirect("~/Class/List.ashx");
            }
            else
            {
                CommonHelper.OutputErrorHtml("删除失败");
            }
        }

28节
NET代码运行在服务器JS运行在客服端

//1
alert('哈哈'); //是阻塞执行,只有窗口关闭才会执行后面的代码
//2
alert('删除成功'); //输出给浏览器是js代码,但是对服务器就是一段字符串,alert是运行在浏览器端得,所以不会等用户关闭alert之后才向后执行
context.Response.Redirect('sefe1.html');
//3
MessageBox.Show("删除成功"); //可以阻塞C#运行,但是这个对话框是弹在服务器的,用户右看不到
context.Response.Redirect('errorMsg.html');
//4    正确的实现
response.write("<script type='text/javascript'>alert('删除成功');location href='errorMsg.html';</script>")

File.WriteAllBytes("d:\\1.exe",new byte[]{3,5,6,7,5543}); //用户访问时,写的.exe病毒也是写在服务器端的

29节
网站安全(不要相信浏览器)

//取款
因为用户可以通过各种手段伪造http请求,服务器必须做教验
如果只是把id藏起来,依然不安全,因为可以通过地址拿到数据
//IP地址不可以造假,但是可以通过代码服务器来转发,服务器拿到的就是代理服务器的IP
//投票网站如何避免刷票 (不用用IP,互联网中也无法获得用户的MAC地址,使用验证码、手机号)

//-------------------Day4-----------------
四章

30节
文本自增演示HttpHandler不记状态

//复制一个.ashx需要改类名,再改文件中的class名
浏览器记不住上次提交的值,下次再提交给服务器相当于重新再来
每次请求都会重新new一个新的对象HttpHandler
HttpHandler记忆--隐藏字段hidden,Cookie,Session
//1    hidden:html的hidden记忆ashx的值并表单提交给HttpHandler

context.Response.ContentType = "text/html";
            string save = context.Request["save"];
            string htmlStr = CommonHelper.OutputHtml("~/IncAddself2.html");
            if(string.IsNullOrEmpty(save)) //第一次进入
            {
                string html = htmlStr.Replace("@number", "0");
                context.Response.Write(html);
            }
            else //提交进入
            {
                int number =Convert.ToInt32( context.Request["number"]);
                number++;
                string html = htmlStr.Replace("@number", number.ToString());
                context.Response.Write(html);
            }

<form action="IncAddSelf2.ashx" method="post">
        @number
        <input type="text" name="number" value="@number" />
        <input type="submit" name="save" style="width:@number0px" value="提交" />
    </form>

31节
Cookie入门

每次向服务器请求,除了表单信息,还需把和站点有关的(服务器给它的)所有Cookie都提交给服务器
在服务器把cookie写入浏览器
//CookieTest1.ashx
HttpCookie cookie=new HttpCookie("test");
cookie.Value="rupeng.com"; //Cookie:键值对
context.Response.SetCookie(cookie);
读取Cookie
//CookieTest2.ashx
HttpCookie cookie1 = context.Request["test"];
context.Response.Write(cookie==null?"没有cookie":cookie.Value); //cookie的值发生改变,下次响应才会改变
//2    Cookie:上次在服务器设置的Cookie,下次可以直接读取和更改该Key的Cookie值
    //CookieTest1.ashx
            HttpCookie cookie = new HttpCookie("test");
            cookie.Value = "rupeng.com";
            context.Response.SetCookie(cookie);
    //CookieTest2.ashx
            HttpCookie cookie1 = context.Request.Cookies["test"];
            context.Response.Write(cookie1 == null ? "没有该key的Cookie" : cookie1.Value);
            cookie1.Value = "iloveyou"; //更改cookie的值
            context.Response.SetCookie(cookie1.Value);

32节
Cookie的细节问题

cookie的有效时间是程序运行期间
cookie.Expires=DateTime.Now.AddSeconds(20); //在DateTime的基础上增加20秒,返回新的DateTIme对象
如果不设定Expires超时时间,则关闭浏览器Cookie失效
如果设定Expires超时时间,,除非到期,否则下次访问浏览器Cookie依然存在
不同浏览器的Cookie是不能共享的
cookie.Value=context.Request.UserAgent; //把UserAgent存入Cookie
浏览器的隐身模式、小号模式,所有的Cookie信息都与主浏览器不一致,达到隐身的效果
Cookie的大小是有限的,不能存储过多的信息
机密信息不能存入Cookie
Cookie是可以被清除的,也许没到Expires就已经过期了

33节
Cookie实现记住用户名

用户第一次进入首先看看Cookie中有没有值
//直接进入时,从Cookie中获得用户名
Http cookieLastUserName = context.Request.Cookies["LastUserName"];
//登陆进入后,把用户名设置到Cookie中
HttpCookie cookieUserName = new HttpCookie("LastUserName");
cookieUserName.Value = username;
cookieUserName.Expires = DateTime.Now.AddDays(7);
context.Response.SetCookie(cookieUserName);

34节
Cookie的深入(*)

//1
关于Cookie的Path(路径)问题
cookie.Path=null;
cookie.Path="/Day4/CookiePath1.ashx"; //Path:谁能读我
如果没有设定Path,则Path的默认值是 "/" ,即当前域名下所有的页面都可以操作这个Cookie
//2
不同域名下的Cookie不相干,但是一个主域名下的两个子域名通过设置Cookie.Domain是可以互相操作(共用)的
www.rupeng.comm
pps.rupeng.comm //这个2个域名为同一个主域名repeng.com下的子域名,他们默认的Cookie也不能互相操作;但是设置Cookie.Domain='.rupeng.com',则他们的子域名都可以操作这个Cookie

35节
Session(会话)入门

服务器端的Cookie,无法造假
给客户一个“身份证”,可以唯一标识这个用户,核心信息放到服务器上,客户端无法去篡改
ASP.net内置了Session机制,.ashx要操作Session必须实现IRequiresSessionState接口,不实现的话Session会为null
这个接口没有任何方法,为标记接口,因为Session处理会稍微降低系统性能,所以这种HttpHandler默认不处理Session,如果实现接口才处理
context.Session["test2"]=888; //cookie只能写string,而session可以是任意类型
int i1=(int)context.Session["test2"]; //错误,因为万一session中为Null,应该int?
Session依赖于Cookie,所在在别的浏览器没有,关闭后也没有了
Cookie存在浏览器中,Session存在服务器中,当前网站的任何一个页面都可能取到Session
服务器会定期销毁服务器端的Session
Session的失效时间是在Web.Config中设置的<SessionState timeout="20"> 设置超时时间,默认时20minutes,也许服务器压力大10minutes就失效了
//Session的保存
context.Session["test1"] = "rupeng.com";
context.Session["test2"] = 888;
//Session的获取
string test1 = (string)context.Session["test1"];
int? test2 = (int?)context.Session["test2"];
context.Response.Write(test1 + "," + test2);
//只有admin这个用户才能访问页面1、页面2,其他用户没有权限访问
//Login1.ashx
    if (string.IsNullOrEmpty(context.Request["login"])) //直接进入
    {
        string username = (string)context.Session["username"];
        context.Response.Write(username == null ? "请先登陆" : "username=" + username + ",登陆成功!");
    }
    else //登陆进入
    {
        string username = context.Request["username"];
        string password = context.Request["password"];
        if (password == "123")
        {
            //登陆成功
            context.Session["username"] = username;
            context.Response.Write("登陆成功"+username);
        }
        else
        {
            context.Response.Write("登陆失败");
        }
    }

//Page1.ashx
    string username = (string)context.Session["username"];
    context.Response.Write(username == "admin" ? "登陆成功" : "username=" + username + ",没有权限进入该页面!");

36节
Session案例:登陆后返回到之前页面

登陆,修改密码,查询余额
//移除google上的自动填充表单内容
//最好把key这些不变值定义为常量,避免写错
public const string LOGINUSERNAME;
web.config中timeout设置session的有效时间
如果访问某个页面进行登陆,登陆之后返回之前的页面(从哪个页面来,登陆后,返回原来页面)
context.Session[Login.LOGNURL]=context.Request.Url.ToString(); //把当前地址存到session
关闭浏览器,服务器的Session还会存在一段时间,而Abandon是立即销毁
context.Session.Abandon(); //销毁
//Login.ashx

public const string LOGINUSERNAME = "loginUserName";
public const string LOGINURL = "loginUrl"; //记录登陆前,进入的页面
public const string YZM = "yanzhengCode";
public void ProcessRequest(HttpContext context)
{
    context.Response.ContentType = "text/html";
    string html = CommonHelper.OutputHtml("~/Login/Login.html");
    if (string.IsNullOrEmpty(context.Request["subLogin"])) //直接进入
    {
        string lastusername = (string)context.Session[LOGINUSERNAME];
        if (lastusername == null) //session中没有登陆信息
        {
            html = html.Replace("@msg", "");
            context.Response.Write(html);
        }
        else //session中有值
        {
            context.Response.Redirect("ExchangePassword.ashx");
        }
    }
    else //登陆进入
    {
        string username = context.Request["username"];
        string password = context.Request["password"];
    string yzm = context.Request["yanzhengCode"];
        //先判断验证码
        string yzmInServer = context.Session[YZM].ToString(); //服务器中的验证码
        if(yzm!=yzmInServer)
        {
            html = html.Replace("@msg", "验证码错误");
            context.Response.Write(html);
            return;
        }
        //判断用户名与密码     
        int i = (int)SqlHelper.ExecuteScalar("select COUNT(*) from T_UserInfoes where UserName=@UserName and Password=@Passwo
            new SqlParameter("@UserName",username),
            new SqlParameter("@Password",password));
        if(i<=0)
        {
            html = html.Replace("@msg","用户名或密码错误");
            context.Response.Write(html);
        }
        else if(i==1) //登陆成功
        {
            context.Session[LOGINUSERNAME] = username;
            string loginUrl = (string)context.Session[LOGINURL];
            //从哪个界面进入,就跳转到哪个界面
            if (loginUrl == null) //没有最先的跳转页面
            {
                context.Response.Redirect("ExchangePassword.ashx");
            }
            else
            {
                context.Response.Redirect(loginUrl);
            }
        }
        else
        {
            html = html.Replace("@msg", "服务器错误,存在相同用户名");
            context.Response.Write(html);
        }
    }

//ExchangePasword.ashx,QueryMoney.ashx

context.Response.ContentType = "text/plain";
    string lastusername = (string)context.Session[Login.LOGINUSERNAME];
    if (lastusername == null) //Session中没有登陆信息
    {
        context.Session[Login.LOGINURL] = context.Request.Url.ToString();
        context.Response.Redirect("Login.ashx");
    }
    else
    {
        context.Response.Write("修改" + lastusername + "的密码.....<a href='EndLogin.ashx'>退出(销毁Session,取消当前会话)</a>" );
    }

EndLogin.ashx

context.Session.Abandon(); //销毁Session,取消当前会话
    context.Response.Redirect("Login.ashx");

//37节
Session案例:验证码

如果没有验证码,可以通过不断试验密码进行暴力破解
验证码是用来区分发出请求信息的是人还是计算机,因为复杂的图片计算机很难识别,而人却可以比较轻松的识别出来的
正确的验证码放在服务器的Session中,用户名输入的与之进行比对
//首先需要生成一张验证码图片(复杂图片需要很多计算机图形学的理论基础)
刷新验证码图片时,如果还是原来的路径YanZhengMa.ashx,因为路径被缓存了,所以不会再刷新,只有路径后+new Date();让这次的src路径与上次不一样,才会重新创建一个随机数,刷新验证码
//然后验证用户名输入验证码是否正确

//generateYanZhengCode.ashx

context.Response.ContentType = "image/jpeg";
    //产生随机数
    Random ran = new Random();
    int num = ran.Next(1000, 10000);
    context.Session[Login.YZM] = num; //把验证码存入会话
    //new一个图片,在画布上画上随机数
    using (Bitmap bmp = new Bitmap(40, 20))
    {
        using (Graphics g = Graphics.FromImage(bmp))
        using(Font font=new Font(FontFamily.GenericSansSerif,10))
        {
            g.DrawString(num.ToString(), font, Brushes.Red, new PointF(0, 0));
        }
        bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);
    }

//Login.ashx

function refreshCode() {
        var im = document.getElementById("im");
        im.src = "generateYanZhengCode.ashx?" + new Date();
    };

<td>验证码</td><td><img src="generateYanZhengCode.ashx" id="im" onclick="refreshCode();" /><input type="text" style="width:60px;" name="yanzhengCode" /></td>

38节
Session的原理

在一个请求期间,为同一个SessionId
Guid算法:Guid guid=Guid.NewGuid();
Guid用于产生全球唯一的字符串,是根据网卡mac地址、系统时间、CPU时钟周期,在同一台多次调用不会重复、在不同电脑同一时间也不会重复
浏览器放了一个SessionId,服务器保存了SessionId的值的对应关系
创建一个SessionId,并设置到Cookie中;保存时,把Value保存到指定SessionId的文件中;取值时,从指定SessionId的文件中取Value-----------------(*)
//原理:浏览器请求服务器,判断Cookie中有没有"SessionId"这样一个Cookie的值,如果Cookie中有个SessionId,如果查到SessionId的值,则在磁盘中找这个文件,如果没有这个文件,则创建一个文件,这个文件就用来保存这个Session的相关信息;如果没有这个SessionId,则创建一个Guid.NewGuid(),然后返回给浏览器.总之,服务器中有放SessionId的文件,保存Session的数据库,浏览器通过这个文件的SessionId来向服务器请求Session数据.
//1CreateSession():创建一个SessionId,设置到Cookie中
//2构造函数:
//如果SessionId不存在,就创建,否则获得这个SessionId,以局部变量存起来
//判断请求中是否有这个SessionId
HttpCookie cookie=context.Request.Cookies[RUPENGSESSIONID];
return cookie!=null; //有SessionId
//3SetValue():把SessionId写入文件(把context用局部变量存起来,方便每次使用)
File.WriteAllText(fullPath,value);
//4GetValue()
File.ReadAllText(fullPath);

//Session原理:RupengSesion.cs
public class RupengSession
{
    private const string RUPENGSESSIONID = "RupengSessionId";
    private string sessionId;
    private HttpContext context;
    public RupengSession(HttpContext context)
    {
        this.context = context;
        //判断Cookie中有没有RupengSessionId
        HttpCookie cookie = context.Request.Cookies[RUPENGSESSIONID];
        if (cookie == null)
        {
            CreateSession();
        }
        else
        {
            this.sessionId = cookie.Value;
        }
    }
    //创建Session
    private void CreateSession()
    {
        Guid guid = Guid.NewGuid();
        this.sessionId = guid.ToString();
        HttpCookie cookie = new HttpCookie(RUPENGSESSIONID);
        cookie.Value = sessionId;
        context.Response.SetCookie(cookie);
    }
    //设值(存入MySession的值)
    public void SetValue(string value)
    {
        string fullPath = context.Server.MapPath("~/MySession/SessionId/" + this.sessionId);
        File.WriteAllText(fullPath, value);
    }
    //取值
    public string GetValue()
    {
        string fullPath = context.Server.MapPath("~/MySession/SessionId/" + this.sessionId);
        if(!File.Exists(fullPath))
        {
            return null;
        }
        return File.ReadAllText(fullPath);
    }

//登录(写入Sessioin):Login1.ashx
RupengSession rupengSession = new RupengSession(context); //把SessionId设置到了Cookie中
rupengSession.SetValue(username); //把username存入SessionId所对应的文件中
context.Response.Redirect("MainPage.ashx");

//读取Session:MainPage.ashx
RupengSession rupengSession = new RupengSession(context);
string username = rupengSession.GetValue();
if (username != null)
{
    context.Response.Write("您当前登录用户名为:" + username);
}
else
{
    context.Response.Write("未登录");
}

39节
改造RupengSession

怎么样使Session放入多个值:对象序列化
序列化:把内存中对象保存为二进制数据
被序列化的对象必须标上[Serializable]
//1序列化对象:把对象保存到流中
Person per=new Person();
BinaryFormatter bf=new BinaryFormatter();
using(Stream stream=File.OpenWrite("d:\\1.bin"))
{
    bf.Serialize(stream,per); //序列化指定对象到指定stream中
}
//2反序列化:从流中读取出来
BinaryFormatter bf=new BinaryFormatter();
using(Stream stream=File.OpenRead("d:\\1.bin"))
{
    Person per=(Person)df.Deserialize(stream);
}

//SetValue(string name,string value)设值时,如果文件存在,就反序列化文件中的内容,放入dict中;如果不存在,创建一个空的dict;添加一个dict,再把dict序列化到指定SessionId文件中
//GetValue(string name)如果文件存在,反序列化为dict,获得指定dict[name];如果文件不存在,返回null

//MySerializeSession.RupengSession.cs
//设值:把这个值保存到指定sessionId的文件中
public void SetValue(string name, string value)
{
    Dictionary<string, string> dict = new Dictionary<string, string>();
    string path = context.Server.MapPath("~/MySerializeSession/SessionId/" + this.sessionId);
    if (File.Exists(path)) //如果文件存在,就从指定文件流中反序列化出其中内容,加入新的值后,再重新序列化到流文件中
    {
        dict = DeserializeFormStream(path);
    }
    dict[name] = value;
    //再重新序列化到流文件中
    using(Stream stream=File.OpenWrite(path))
    {
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(stream, dict); //把指定对象序列化到指定流中
    }
}
//取值:从指定SessionId的文件中获得资格值
public string GetValue(string name)
{
    string path = context.Server.MapPath("~/MySerializeSession/SessionId/" + this.sessionId);
    if(!File.Exists(path))
    {
        return null;
    }
    //如果文件存在
    Dictionary<string, string> dict = new Dictionary<string, string>();
    dict = DeserializeFormStream(path);
    return dict[name];
}
//从流中读取文件并反序列化为对象
private Dictionary<string,string> DeserializeFormStream(string path)
{
    using (Stream stream = File.OpenRead(path))
    {
        BinaryFormatter bf = new BinaryFormatter();
        return (Dictionary<string, string>)bf.Deserialize(stream);
    }
}

//Login1.ashx
RupengSession rupengSession = new RupengSession(context); //把SessionId设置到了Cookie中
rupengSession.SetValue("username", username); //把username存入SessionId所对应的文件中
rupengSession.SetValue("lastLoginTime", DateTime.Now.ToString());

//MainPage.ashx
RupengSession rupengSession = new RupengSession(context);
string username = rupengSession.GetValue("username");
if (username != null)
{
    context.Response.Write("您当前登录用户名为:" + username);
    context.Response.Write("您当前登录时间为:" + rupengSession.GetValue("lastLoginTime"));
}
else
{
    context.Response.Write("未登录");
}

39节
进程外Session

Asp.net中的Session默认保存在Web服务器内存中的(Inprov),Web服务器重启,所有Session数据都会消失
session.web中sessionState中的timeout="10"
避免Session重启后就消失:把Session存在别的地方,如本次的练习,以及把Session存到进程外SqlServer和sessionState
//1 Session保存到SQLServer中配置方法
Windows--NET---4.0.30319--aspnet_regsql.exe--ssadd···(哪个数据库:ip,db,uid,pwd;参数见http://www.cnblogs.com/China-Dragon/archive/2009/05/12/1455147.html)
然后修改web.config中sessionState节点的配置:<sessionState mode="SQLServer" timeout="20" sqlConnectionString="server=.;uid=sa;password=123456;"></sessionState>
//2 Session保存到Windows服务中的StateServer中---怎么配置自己到百度搜
网络项目最好用这种进程外Session

http://www.cnblogs.com/China-Dragon/archive/2009/05/12/1455147.html ----------------------------???---------------------
-E是使用Windows认证,也可以使用数据库认证
aspnet_regsql.exe -ssadd -sstype c -d [DB]  -S [Server] –U [User Name] – P [Password]
2. 修改web.config:
<sessionState mode="SQLServer" allowCustomSqlDatabase="true" sqlConnectionString="data source=[Server];initial catalog=[DB];user id=[User Name];password=[Password]"
                cookieless="false"
                timeout="20" />
如果使用默认的数据库名称,如下:
<sessionState mode="SQLServer" sqlConnectionString="data source=[Server];user id=[User Name];password=[Password]"
                cookieless="false"
                timeout="20" />

//------------------------------------
40节

Asp.Net Core(.net内核)的更多相关文章

  1. ASP.NET Core 中文文档 第三章 原理(15)请求功能

    作者:Steve Smith 翻译:谢炀(kiler398) 校对:姚阿勇(Dr.Yao).孟帅洋(书缘) 涉及到如何处理 HTTP 请求以及响应的独立 Web 服务器功能已经被分解成独立的接口,这些 ...

  2. ASP.NET Core服务器综述

    原文地址:Servers overview for ASP.NET Core By Tom Dykstra, Steve Smith, Stephen Halter, and Chris Ross A ...

  3. 在Linux和Windows的Docker容器中运行ASP.NET Core

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 译者序:其实过去这周我都在研究这方面的内容,结果周末有事没有来得及总结为文章,Scott H ...

  4. 在ASP.NET Core中怎么使用HttpContext.Current

    一.前言 我们都知道,ASP.NET Core作为最新的框架,在MVC5和ASP.NET WebForm的基础上做了大量的重构.如果我们想使用以前版本中的HttpContext.Current的话,目 ...

  5. 跨平台运行ASP.NET Core 1.0

    前言 首先提一下微软更名后的叫法: ASP.NET 5 更名为 ASP.NET Core 1.0 .NET Core 更名为 .NET Core 1.0 Entity Framework 7 更名为  ...

  6. 丙申年把真假美猴王囚禁在容器中跑 ASP.NET Core 1.0

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  7. Docker容器中运行ASP.NET Core

    在Linux和Windows的Docker容器中运行ASP.NET Core 译者序:其实过去这周我都在研究这方面的内容,结果周末有事没有来得及总结为文章,Scott Hanselman就捷足先登了. ...

  8. 跨平台运行ASP.NET Core 1.0(转载)

    前言 首先提一下微软更名后的叫法: ASP.NET 5 更名为 ASP.NET Core 1.0 .NET Core 更名为 .NET Core 1.0 Entity Framework 7 更名为  ...

  9. 10分钟学会在windows/Linux下设置ASP.Net Core开发环境并部署应用

    创建和开发ASP.NET Core应用可以有二种方式:最简单的方式是通过Visual Studio 2017 来创建,其优点是简单方便,但需要安装最新版本Visual Studio 2017 prev ...

随机推荐

  1. jsp bean标签

    jsp中存在一个奇奇怪怪的bean标签. 例如 现在在java包中定义一个类test2 package bean; public class test { private int number; pu ...

  2. linux网卡速率和双工模式的配置

    linux网卡速率和双工模式的配置 (2012-09-06 14:39:57) 转载▼ 标签: 科技 网络接口 协商 网卡 工具 it 分类: Linux 改变网络接口的速度和协商方式的工具miito ...

  3. 全球说:要给 OneAlert 点100个赞

    客户背景 「全球说」 Talkmate,是北京酷语时代教育科技有限公司(酷语科技)旗下产品,酷语科技是一家诞生于中国的语言技术公司,致力于为全球用户提供一个全新的多语言学习和社交网络平台 . 全球说是 ...

  4. Linked List vs Array

    Both Arrays and Linked List can be used to store linear data of similar types, but they both have so ...

  5. mac上eclipse上配置hadoop

    在mac上安装了eclipse之后,配置hadoop其实跟在linux上配置差不多,只是mac上得eclipse和界面和linux上得有点不同. 一:安装eclipse eclipse得安装比较简单, ...

  6. POJ1321棋盘问题

    http://poj.org/problem?id=1321 题意 : 我能说这是迄今为止见到的POJ上第二道中文题吗,既然是中文也很好理解,就不详述了 思路 : 典型的深搜DFS ; #includ ...

  7. MYSQL日常操作命令再熟悉

    1,创建用户及密码: CREATE USER 'user'@'%' IDENTIFIED BY 'password'; 2,创建数据库: create database PDB_chengang de ...

  8. struts2 json关于Date日期的解析

    在get方法前加上: @JSON(format="yyyy-MM-dd HH:mm:ss")

  9. java中的freopen

    在做ACM题目的时候,为节省输入测试数据的时间,我们通常将数据复制到一个文本文档里,然后从文档里读出,避免在控制台一个数据一个数据的输入. 之前一直用的C/C++,freopen用起来很方便,如下: ...

  10. [codility]CountDiv

    https://codility.com/demo/take-sample-test/count_div 此题比较简单,是在O(1)时间里求区间[A,B]里面能被K整除的数字,那么就计算一下就能得到. ...