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 [email protected]", 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 [email protected]", 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 [email protected]",
                    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 [email protected]",
                        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 [email protected],[email protected],[email protected] where [email protected]", 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 [email protected]",
                new SqlParameter() { ParameterName = "@CId", Value = cid });
            int i = -1;
            if(count>0) //有该班级的学生
            {
                i = SqlHelper.ExecuteNonQuery("delete from T_Students where [email protected]",
                    new SqlParameter() { ParameterName = "@CId", Value = cid });
            }
            i = SqlHelper.ExecuteNonQuery("delete from T_Classes where [email protected]",
                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 [email protected] and [email protected]
            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节

时间: 2024-10-21 16:27:41

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

CentOs 7.2 + Nginx 1.10.2 + MusicStore(asp.net core mvc 3 项目)虚拟机完整搭建流程分享

原创辛苦,谢绝转载! 虚拟机说明 搭建这个虚拟机是为了验证Asp.net Core程序在CentOs操作系统上可以运行的. #软件环境版本枚举OS:CentOS Linux release 7.2.1511 (Core) OS Kernel:Linux version 3.10.0-327.36.3.el7.x86_64 ([email protected]) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC) ) #1 SMP Mon Oct

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

(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 译者序:其实过去这周我都在研究这方面的内容,结果周末有事没有来得及总结为文章,Scott Hanselman就捷足先登了.那么我就来翻译一下这篇文章,让更多的中文读者看到.当然Scott遇到的坑我也遇到了. 不过首先,对于不熟悉的朋友我还是来解释一下Linux容器和Windows容器的概念. 由于容器成为虚拟化和应用托管的一种不可避免的选项,Windows也开始为公众提供容器功能(其实微软具备和使用

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

丙申年把真假美猴王囚禁在容器中跑 ASP.NET Core 1.0? 警告 您当前查看的页面是未经授权的转载! 如果当前版本排版错误,请前往查看最新版本:http://www.cnblogs.com/qin-nz/p/aspnetcore-run-on-mono-in-year-of-monkey.html 提示 更新时间:2016年02月07日. 各位程序媛/程序猿们,猴年快乐. 相信不少媛/猿都是被标题吸引来的,那我我先解释下标题. 提示 本文是一篇半科普文,不对技术细节进行深入探究. 标题

Jexus部署Asp.Net Core项目

在之前的我的博客项目中,我将.net Core发布到Cent OS 上,使用的Nginx代理以及Supervisor进程守护,看过我的博客的童鞋,也会发现,这种方式比较麻烦,光命令行就看的头大,总共部署了两次还是三次,可是每次一样都是要翻博客翻资料,想想还是IIS好用,点几下鼠标就完成了,没有这么多步骤.之前也一直想尝试下使用Jexus部署我的项目,也一直没有时间搞,今天趁着外面下雨,就仔细学习下这个东东. Jexus百度百科: Jexus 即 Jexus Web Server,简称JWS,是L

Docker容器中运行ASP.NET Core

在Linux和Windows的Docker容器中运行ASP.NET Core 译者序:其实过去这周我都在研究这方面的内容,结果周末有事没有来得及总结为文章,Scott Hanselman就捷足先登了.那么我就来翻译一下这篇文章,让更多的中文读者看到.当然Scott遇到的坑我也遇到了. 不过首先,对于不熟悉的朋友我还是来解释一下Linux容器和Windows容器的概念. 由于容器成为虚拟化和应用托管的一种不可避免的选项,Windows也开始为公众提供容器功能(其实微软具备和使用容器技术很久了).这

ASP.NET Core 1.0

跨平台运行ASP.NET Core 1.0 前言 首先提一下微软更名后的叫法: ASP.NET 5 更名为 ASP.NET Core 1.0 .NET Core 更名为 .NET Core 1.0 Entity Framework 7 更名为 Entity Framework Core 1.0 或者简称 EF Core 1.0 现在伴随着ASP.NET Core 1.0 RC2版的更新速度,许多官方文档都跟不上,还停留在RC1版的使用方式上(RC1版是继Beta版之后第一个发布的稳定版本).RC

在IIS上发布并运行ASP.NET Core

英文原文地址:https://weblog.west-wind.com/posts/2016/Jun/06/Publishing-and-Running-ASPNET-Core-Applications-with-IIS 当构建一个ASP.NET Core应用程序并且计划将其运行在IIS中时,你会发现Core应用程序和之前版本的ASP.NET程序在IIS中的运行方式是完全不一样的. 在本篇文章中,你可以了解ASP.NET Core是如何运行在IIS上下文中的,怎样才能把ASP.NET Core应

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

一.前言 我们都知道,ASP.NET Core作为最新的框架,在MVC5和ASP.NET WebForm的基础上做了大量的重构.如果我们想使用以前版本中的HttpContext.Current的话,目前是不可用的,因为ASP.NET Core中是并没有这个API的. 当然我们也可以通过在Controller中访问HttpContext,但是某些情况下,这样使用起来还是不如HttpContext.Current方便. 二.IHttpContextAccessor 利用ASP.NET Core的依赖

ASP.NET Core 2.2 基础知识(十一) ASP.NET Core 模块

原文:ASP.NET Core 2.2 基础知识(十一) ASP.NET Core 模块 ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET Core 随附两种服务器实现: Kestrel 是适用于 ASP.NET Core 的默认跨平台 HTTP 服务器. HTTP.sys 是仅适用于 Windows 的 HTTP 服务器,它基于 HTTP.sy