一.说明
此文是小白在学习张晨光老师的视频教学<<Asp.Net WEB服务器编程技术>>中做的学习笔记,一些知识点也是跟着教程走的,大家也可以去老师的主页去学习,谢谢大家.
二.生成验证码图片(CodeHandler.ashx)
上一节,我们使用的是checkcode.aspx.cs来处理生成验证码图片,今天我们在Handler文件夹下创建一般处理程序CodeHandler.ashx,来代替.代码如下:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.SessionState;
namespace MyMusci.Handler
{
/// <summary>
/// CodeHandler 的摘要说明
/// </summary>
public class CodeHandler : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string chkCode = string.Empty;
int ix, iy;
ix = 140;
iy = 40;
//颜色列表,用于验证码、噪线、噪点
Color[] color = { Color.Black, Color.Red, Color.Blue, Color.Green, Color.Orange, Color.Brown, Color.Brown, Color.DarkBlue };
//字体列表,用于验证码
string[] font = { "Times New Roman", "MS Mincho", "Book Antiqua", "Gungsuh", "MingLiU", "Arial" };
//验证码的字符集,去掉了一些容易混淆的字符
char[] character = { '2', '3', '4', '5', '6', '8', '9', '0', '1', '小', '白' };
Random rnd = new Random();
//生成验证码字符串
for (int i = 0; i < 4; i++)
{
chkCode += character[rnd.Next(character.Length)];
}
Bitmap bmp = new Bitmap(ix, iy);
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.White);
//画噪线
for (int i = 0; i < 10; i++)
{
int x1 = rnd.Next(ix);
int y1 = rnd.Next(iy);
int x2 = rnd.Next(ix);
int y2 = rnd.Next(iy);
Color clr = color[rnd.Next(color.Length)];
g.DrawLine(new Pen(clr), x1, y1, x2, y2);
}
//画验证码字符串
for (int i = 0; i < chkCode.Length; i++)
{
string fnt = font[rnd.Next(font.Length)];
Font ft = new Font(fnt, iy/2, FontStyle.Bold);
Color clr = color[rnd.Next(color.Length)];
g.DrawString(chkCode[i].ToString(), ft, new SolidBrush(clr), (float)i * 30 + 2, (float)2);
}
//画噪点
for (int i = 0; i < 50; i++)
{
int x = rnd.Next(bmp.Width);
int y = rnd.Next(bmp.Height);
Color clr = color[rnd.Next(color.Length)];
bmp.SetPixel(x, y, clr);
}
//将验证码写入SESSION,为什么第二个页面没法获取值???
//一般处理程序增加接口文件;
HttpContext.Current.Session["Code"] = chkCode.ToUpper();
//清除该页输出缓存,设置该页无缓存
context.Response.Buffer = true;
context.Response.ExpiresAbsolute = System.DateTime.Now.AddMilliseconds(0);
context.Response.Expires = 0;
context.Response.CacheControl = "no-cache";
context.Response.AppendHeader("Pragma", "No-Cache");
//将验证码图片写入内存流,并将其以 "image/Png" 格式输出
//我这个页面返回的是图片;
MemoryStream ms = new MemoryStream();
try
{
bmp.Save(ms, ImageFormat.Png);
context.Response.ClearContent();
context.Response.ContentType = "image/Png";
context.Response.BinaryWrite(ms.ToArray());
}
finally
{
//显式释放资源
bmp.Dispose();
g.Dispose();
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
三.登录页面添加验证码(login_new.aspx)
因为我们更换了验证码的生成程序,所以也要在登录界面更换对应代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="login_new.aspx.cs" Inherits="MyMusci.login_new" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<link href="bootstrap-5.1.3-dist/css/bootstrap.css" rel="stylesheet" />
<script src="bootstrap-5.1.3-dist/js/bootstrap.bundle.js"></script>
<script src="js/jquery.js"></script>
<style>
/*将整个登入的div垂直居中*/
.all {
width: 700px;
height: 260px;
background-color: rgba(205,197,191,0.8);
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
padding:0;
}
body {
background-image: url("img/dm.jpg");
/*整个图片作为背景,不够自动拉伸*/
background-size: cover;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div class="container mt-3">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<table class="table all">
<tr>
<td class="table-primary display-3 text-center text-primary" colspan="3">登录界面</td>
</tr>
<tr>
<td>账户</td>
<td>
<asp:TextBox ID="userName" runat="server"></asp:TextBox>
</td>
<td>
<asp:RequiredFieldValidator ID="rfv_useName" runat="server" ControlToValidate="userName" Display="Dynamic" ErrorMessage="RequiredFieldValidator" ForeColor="Red">账户不可为空</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="rev_userName" runat="server" ControlToValidate="userName" Display="Dynamic" ErrorMessage="RegularExpressionValidator" ForeColor="Red" ValidationExpression="\w{5,13}">您输入的账户异常(5-12位)</asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td class="auto-style2">密码</td>
<td class="auto-style2">
<asp:TextBox ID="userPwd" runat="server"></asp:TextBox>
</td>
<td class="auto-style2">
<asp:RequiredFieldValidator ID="rfv_userPwd" runat="server" ControlToValidate="userPwd" Display="Dynamic" ErrorMessage="RequiredFieldValidator" ForeColor="Red">密码不可为空</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="rev_userPwd" runat="server" ControlToValidate="userPwd" Display="Dynamic" ErrorMessage="RegularExpressionValidator" ForeColor="Red" ValidationExpression="\w{8,13}">您输入的密码异常(8位)</asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td>
验证码</td>
<td>
<asp:TextBox ID="code" runat="server"></asp:TextBox>
</td>
<td><img id="imgcode" src="Handler/CodeHandler.ashx" />
<asp:Label ID="codeText" runat="server" Text=""></asp:Label></td>
</tr>
<tr>
<td>
<asp:Button ID="btn_sub" runat="server" class="btn btn-primary" OnClick="btn_sub_Click" Text="登录" />
</td>
<td>
<asp:LinkButton ID="LinkButton1" runat="server" class="btn btn-secondary" PostBackUrl="~/RegUser.aspx" CausesValidation="False">注册</asp:LinkButton>
</td>
<td> </td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
<script>
//图片点击事件
$("#imgcode").click(function () {
$("#imgcode").attr("src", "Handler/CodeHandler.ashx?t=" + Math.random());
})
</script>
</body>
</html>
后台代码也作对应的代码添加(login_new.aspx.cs):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Collections;
namespace MyMusci
{
public partial class login_new : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
/// <summary>
/// 重置按钮点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btn_reset_Click(object sender, EventArgs e)
{
userName.Text = "";
userPwd.Text = "";
}
/// <summary>
/// 登录按钮点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btn_sub_Click(object sender, EventArgs e)
{
//测试
//if ("administrator".Equals(userName.Text) && "12345678".Equals(userPwd.Text)) {
// Response.Redirect("index.aspx");
//}
//这里判断验证控件是否通过,如果没通过,则返回
if (!rev_userName.IsValid || !rev_userPwd.IsValid) {
return;
}
//这里判断用户是否输入了验证码的输入框的值,如果没有输入,提示用户,并返回
if (code.Text != Session["Code"].ToString())
{
codeText.Text = "验证码不正确,请重新输入";
return;
}
//否则清空提示值,并且让代码正常运行下去
else {
codeText.Text = "";
}
string sql = "SELECT COUNT(*) FROM user_all WHERE user_name=?name AND user_pwd=?pwd";
Hashtable ht = new Hashtable();
ht.Add("name", userName.Text.ToString());
ht.Add("pwd", ChangPwd.UserMd5(userPwd.Text.ToString()));
int resilc = ToolMysqlDate.excutScal(sql, ht);
if (resilc > 0)
{
//将用户名绑定到Session
Session["userName"] = userName.Text.ToString();
//Response是服务器发出的响应,耗费资源,服务器的内存和网络的带宽
//Response.Redirect("index.aspx");
ScriptManager.RegisterStartupScript(UpdatePanel1, typeof(UpdatePanel), "ok_login", "alert('您已成功登录!');location.href='index.aspx'", true);
}
else
{
//Response.Write("<script>alert('您输入的账户或密码有误,请核对后输入!!!')</script>");
ScriptManager.RegisterStartupScript(UpdatePanel1, typeof(UpdatePanel), "error_login", "alert('您输入的账户或密码有误,请核对后输入!!!')", true);
}
}
}
}
四.效果
当验证通过,且验证码正确时:
当验证码不正确时: