Asp.Net Core(.net内核)
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問服務器說“我本地的文件的修改日期是。。?!?#xff0c;服務器端如果發現文件還是那個文件,則告訴瀏覽器(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 οnclick='return confirm(\"你真的要刪除嗎?\")' href='PersonDelete.ashx?id=")
?.Append(row["id"]).Append("'>刪除</a></td>");
?//2
?οnclick=\"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 οnclick=\"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" οnclick="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節
轉載于:https://www.cnblogs.com/adolphyang/p/4766770.html
總結
以上是生活随笔為你收集整理的Asp.Net Core(.net内核)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java的4种代码块
- 下一篇: 用DOM解析XML