oa_mvc_easyui_项目搭建及登录页面验证码(1)
1.空项目的搭建,三层的搭建(各层之中的引用)
webapp:bll,model,common
bll:dal,model
dal:model
2.SQL表
ItcastDb:T_UserInfo,T_News,T_NewComments
T_UserInfo:
USE [ItcastDb] GO /****** Object: Table [dbo].[T_UserInfo] Script Date: 05/24/2017 09:13:43 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[T_UserInfo]( [id] [int] IDENTITY(1,1) NOT NULL, [UserName] [nvarchar](50) NULL, [UserPwd] [nvarchar](50) NULL, [UserMail] [nvarchar](50) NULL, [RegTime] [datetime] NULL, CONSTRAINT [PK_T_UserInfo] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO ALTER TABLE [dbo].[T_UserInfo] ADD CONSTRAINT [DF_T_UserInfo_RegTime] DEFAULT (getdate()) FOR [RegTime] GO
T_News:
USE [ItcastDb] GO /****** Object: Table [dbo].[T_News] Script Date: 05/24/2017 09:13:38 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[T_News]( [id] [int] IDENTITY(1,1) NOT NULL, [Title] [nvarchar](50) NULL, [Msg] [nvarchar](2000) NULL, [SubDateTime] [datetime] NULL, [Author] [nvarchar](50) NULL, [ImagePath] [nvarchar](50) NULL, CONSTRAINT [PK_T_News] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
T_NewComments:
USE [ItcastDb] GO /****** Object: Table [dbo].[T_NewComments] Script Date: 05/24/2017 09:13:28 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[T_NewComments]( [id] [int] IDENTITY(1,1) NOT NULL, [NewId] [int] NULL, [Msg] [nvarchar](50) NULL, [CreateDateTime] [datetime] NULL, CONSTRAINT [PK_T_NewComments] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
3.Model实体类的编写
T_NewComments:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Itcast.CMS.Model { public class T_NewComments { public int Id { get; set; } public int NewId { get; set; } public string Msg { get; set; } public DateTime CreateDateTime { get; set; } } }
T_UserInfo:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Itcast.CMS.Model { public class T_UserInfo { public int Id { get; set; } public string UserName { get; set; } public string UserPwd { get; set; } public string UserMail { get; set; } public DateTime RegTime { get; set; } } }
T_News:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Itcast.CMS.Model { public class T_News { public int Id { get; set; } public string Title { get; set; } public string Msg { get; set; } public DateTime SubDateTime { get; set; } public string Author { get; set; } public string ImagePath { get; set; } } }
4.DAl层编写SqlHelp类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; using System.Data.SqlClient; namespace Itcast.CMS.DAL { public class SqlHelper { /// <summary> /// 自定义数据库连接字符串 /// </summary> public static string ConnString = @"Data Source=.;Initial Catalog=zhigongWebDB; User ID=sa;Pwd=123456"; /// <summary> /// 应用程序下获取连接字符串 /// </summary> //public static string ConnString //{ // get { // return System.Configuration.ConfigurationManager.ConnectionStrings["connstring"].ToString(); // } //} /// <summary> /// 执行一个Sql语句返回受影响的行数 /// </summary> /// <param name="sql">insert,update,delete或相关的存储过程</param> /// <param name="type">命令类型:SQL语句还是存储过程</param> /// <param name="pars">SQL语句所需要的参数</param> public static int ExcuteSQLReturnInt(string sql, CommandType type, params SqlParameter[] pars) { //定义连接对象 SqlConnection conn = new SqlConnection(ConnString); //判断连接对象的状态,并且打开 if (conn.State == ConnectionState.Closed || conn.State == ConnectionState.Broken) { conn.Open(); } try { //实例化命令对象 SqlCommand cmd = new SqlCommand(sql, conn); //判断CommandType类型是否是SQL语句还是存储过程 cmd.CommandType = type; if (pars != null && pars.Length > 0) { foreach (SqlParameter p in pars) { cmd.Parameters.Add(p); } } //调用方法执行SQL语句或存储过程 int count = cmd.ExecuteNonQuery(); return count; } catch (Exception ex) { return 0; } finally { //记得要关闭连接 conn.Close(); } } /// <summary> /// 执行一个Sql语句或存储过程,返回一条记录,sqldataReader /// </summary> /// <param name="sql">select语句,或相关的存储过程</param> /// <param name="type">指定命令类型,sql语句还是存储过程,默认的是sql语句</param> /// <param name="pars">参数的集合</param> /// <returns></returns> public static SqlDataReader ExcuteSqlReturnReader(string sql, CommandType type, SqlParameter[] pars) { SqlConnection conn = new SqlConnection(ConnString); if (conn.State == ConnectionState.Closed || conn.State == ConnectionState.Broken) { conn.Open(); } SqlCommand cmd = new SqlCommand(sql, conn); if (pars != null && pars.Length > 0) { foreach (SqlParameter p in pars) { cmd.Parameters.Add(p); } } cmd.CommandType = type; //当reader.close(),也就是关闭了datareader时,CommandBehavior.CloseConnection 也会关闭连接! SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection); return reader; } /// <summary> /// 执行一个sql语句或存储过程,不带参数的!返回一天记录 sqldataReader /// </summary> /// <param name="sql"></param> /// <param name="type"></param> /// <returns></returns> public static SqlDataReader ExcuteSqlReturnReader(string sql, CommandType type) { SqlConnection conn = new SqlConnection(ConnString); if (conn.State == ConnectionState.Closed || conn.State == ConnectionState.Broken) { conn.Open(); } SqlCommand cmd = new SqlCommand(sql, conn); cmd.CommandType = type; //当reader.close(),也就是关闭了datareader时,CommandBehavior.CloseConnection 也会关闭连接! SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection); return reader; } /// <summary> /// 执行一个Sql语句或存储过程,返回一个数据集,dataset /// </summary> /// <param name="sql">select语句或相关的存储过程</param> /// <param name="type">命令类型</param> /// <param name="pars">命令类型</param> /// <returns>DataSet</returns> public static DataSet SelectSqlReturnDataset(string sql, CommandType type, SqlParameter[] pars) { SqlConnection conn = new SqlConnection(ConnString); //数据集识别器对象SqlDataAdapter 会自动打开数据库链接! SqlDataAdapter sda = new SqlDataAdapter(sql, conn); if (pars != null && pars.Length > 0) { foreach (SqlParameter p in pars) { sda.SelectCommand.Parameters.Add(p); } } sda.SelectCommand.CommandType = type; DataSet ds = new DataSet(); sda.Fill(ds); return ds; } /// <summary> /// 执行一个sql语句返回一个数据表对象 /// </summary> /// <param name="sql">select</param> /// <param name="type">命令类型</param> /// <param name="pars">参数集合</param> /// <returns>DataTable</returns> public static DataTable SelectSqlReturnDataTable(string sql, CommandType type, SqlParameter[] pars) { SqlConnection conn = new SqlConnection(ConnString); SqlDataAdapter sda = new SqlDataAdapter(sql, conn); if (pars != null && pars.Length > 0) { foreach (SqlParameter p in pars) { sda.SelectCommand.Parameters.Add(p); } } sda.SelectCommand.CommandType = type; DataTable dt = new DataTable(); sda.Fill(dt); return dt; } //******************************************************************* //SelectSqlReturnDataTable方法的重载,不传参数的情况下 /// <summary> /// 执行一个sql语句返回一个数据表对象,不传参数 /// </summary> /// <param name="sql">select</param> /// <param name="type">命令类型</param> /// <returns></returns> public static DataTable SelectSqlReturnDataTable(string sql, CommandType type) { SqlConnection conn = new SqlConnection(ConnString); SqlDataAdapter sda = new SqlDataAdapter(sql, conn); sda.SelectCommand.CommandType = type; DataTable dt = new DataTable(); sda.Fill(dt); return dt; } /// <summary> /// 执行一个sql语句或相关的存储过程,返回一个值 /// </summary> /// <param name="sql">select count(*) from tablename where ....</param> /// <param name="type">命令类型</param> /// <param name="pars">所需的参数</param> /// <returns>object</returns> public static object selectSqlReturnObject(string sql, CommandType type, SqlParameter[] pars) { SqlConnection conn = new SqlConnection(ConnString); if (conn.State == ConnectionState.Closed || conn.State == ConnectionState.Broken) { conn.Open(); } try { SqlCommand cmd = new SqlCommand(sql, conn); cmd.CommandType = type; if (pars != null && pars.Length > 0) { foreach (SqlParameter p in pars) { cmd.Parameters.Add(p); } } object obj = cmd.ExecuteScalar(); return obj; } catch (Exception ex) { return null; } finally { conn.Close(); } } } }
5.新建登录控制器(LoginControllers),并添加index视图
**更改路由:Global.asax--RouteConfig.RegisterRoutes(RouteTable.Routes)
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace Itcast.CMS.WebApp { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional } ); } } }
6.新建登录页面,及验证码
Common通用层中新建ValidateCode类,用于生产验证码(引用命名空间:system.Drawing,system.Web)
ValidateCode:
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web; namespace Itcast.CMS.Common { public class ValidateCode { public ValidateCode() { } /// <summary> /// 验证码的最大长度 /// </summary> public int MaxLength { get { return 10; } } /// <summary> /// 验证码的最小长度 /// </summary> public int MinLength { get { return 1; } } /// <summary> /// 生成验证码 /// </summary> /// <param name="length">指定验证码的长度</param> /// <returns></returns> public string CreateValidateCode(int length) { int[] randMembers = new int[length]; int[] validateNums = new int[length]; string validateNumberStr = ""; //生成起始序列值 int seekSeek = unchecked((int)DateTime.Now.Ticks); Random seekRand = new Random(seekSeek); int beginSeek = (int)seekRand.Next(0, Int32.MaxValue - length * 10000); int[] seeks = new int[length]; for (int i = 0; i < length; i++) { beginSeek += 10000; seeks[i] = beginSeek; } //生成随机数字 for (int i = 0; i < length; i++) { Random rand = new Random(seeks[i]); int pownum = 1 * (int)Math.Pow(10, length); randMembers[i] = rand.Next(pownum, Int32.MaxValue); } //抽取随机数字 for (int i = 0; i < length; i++) { string numStr = randMembers[i].ToString(); int numLength = numStr.Length; Random rand = new Random(); int numPosition = rand.Next(0, numLength - 1); validateNums[i] = Int32.Parse(numStr.Substring(numPosition, 1)); } //生成验证码 for (int i = 0; i < length; i++) { validateNumberStr += validateNums[i].ToString(); } return validateNumberStr; } /// <summary> /// 创建验证码的图片 /// </summary> /// <param name="context">要输出到的page对象</param> /// <param name="validateNum">验证码</param> public void CreateValidateGraphic(string validateCode, HttpContext context) { Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 12.0), 22); Graphics g = Graphics.FromImage(image); try { //生成随机生成器 Random random = new Random(); //清空图片背景色 g.Clear(Color.White); //画图片的干扰线 for (int i = 0; i < 25; i++) { int x1 = random.Next(image.Width); int x2 = random.Next(image.Width); int y1 = random.Next(image.Height); int y2 = random.Next(image.Height); g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2); } Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic)); LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true); g.DrawString(validateCode, font, brush, 3, 2); //画图片的前景干扰点 for (int i = 0; i < 100; i++) { int x = random.Next(image.Width); int y = random.Next(image.Height); image.SetPixel(x, y, Color.FromArgb(random.Next())); } //画图片的边框线 g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1); //保存图片数据 MemoryStream stream = new MemoryStream(); image.Save(stream, ImageFormat.Jpeg); //输出图片流 context.Response.Clear(); context.Response.ContentType = "image/jpeg"; context.Response.BinaryWrite(stream.ToArray()); } finally { g.Dispose(); image.Dispose(); } } /// <summary> /// 得到验证码图片的长度 /// </summary> /// <param name="validateNumLength">验证码的长度</param> /// <returns></returns> public static int GetImageWidth(int validateNumLength) { return (int)(validateNumLength * 12.0); } /// <summary> /// 得到验证码的高度 /// </summary> /// <returns></returns> public static double GetImageHeight() { return 22.5; } //C# MVC 升级版 /// <summary> /// 创建验证码的图片 /// </summary> /// <param name="containsPage">要输出到的page对象</param> /// <param name="validateNum">验证码</param> public byte[] CreateValidateGraphic(string validateCode) { Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 12.0), 22); Graphics g = Graphics.FromImage(image); try { //生成随机生成器 Random random = new Random(); //清空图片背景色 g.Clear(Color.White); //画图片的干扰线 for (int i = 0; i < 25; i++) { int x1 = random.Next(image.Width); int x2 = random.Next(image.Width); int y1 = random.Next(image.Height); int y2 = random.Next(image.Height); g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2); } Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic)); LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true); g.DrawString(validateCode, font, brush, 3, 2); //画图片的前景干扰点 for (int i = 0; i < 100; i++) { int x = random.Next(image.Width); int y = random.Next(image.Height); image.SetPixel(x, y, Color.FromArgb(random.Next())); } //画图片的边框线 g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1); //保存图片数据 MemoryStream stream = new MemoryStream(); image.Save(stream, ImageFormat.Jpeg); //输出图片流 return stream.ToArray(); } finally { g.Dispose(); image.Dispose(); } } } }
LoginController控制器中,新建ValidateCode()方法用于生产验证码。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Itcast.CMS.WebApp.Controllers { public class LoginController : Controller { //约定大于配置 // GET: /Login/ public ActionResult Index() { return View(); } /// <summary> /// 生产验证码 /// </summary> /// <returns></returns> public ActionResult ValidateCode() { Common.ValidateCode validateCode = new Common.ValidateCode(); string code = validateCode.CreateValidateCode(4);//生成验证码 Session["validateCode"] = code;//存储于Session中 byte[] buffer = validateCode.CreateValidateGraphic(code);//创建验证码的图片 return File(buffer, "image/jpeg"); } } }
视图代码......
@{ Layout = null; } <!DOCTYPE html> <html> <head> <title>Itcast.CMS后台台管理系统登录</title> <script type="text/javascript"> if (window.parent.window != window) { window.top.location.href = "/Home/CheckLogin"; } </script> <script src="~/Scripts/jquery-1.8.2.min.js"></script> <script src="~/Scripts/jquery.validate.min.js"></script> <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script> <script type="text/javascript"> </script> <style type="text/css"> * { padding: 0; margin: 0; } body { text-align: center; background: #4974A4; } #login { width: 740px; margin: 0 auto; font-size: 12px; } #loginlogo { width: 700px; height: 100px; overflow: hidden; background: url('/Content/Images/login/logo.png') no-repeat; margin-top: 50px; } #loginpanel { width: 729px; position: relative; height: 300px; } .panel-h { width: 729px; height: 20px; background: url('/Content/Images/login/panel-h.gif') no-repeat; position: absolute; top: 0px; left: 0px; z-index: 3; } .panel-f { width: 729px; height: 13px; background: url('/Content/Images/login/panel-f.gif') no-repeat; position: absolute; bottom: 0px; left: 0px; z-index: 3; } .panel-c { z-index: 2; background: url('/Content/Images/login/panel-c.gif') repeat-y; width: 729px; height: 300px; } .panel-c-l { position: absolute; left: 60px; top: 40px; } .panel-c-r { position: absolute; right: 20px; top: 50px; width: 222px; line-height: 200%; text-align: left; } .panel-c-l h3 { color: #556A85; margin-bottom: 10px; } .panel-c-l td { padding: 7px; } .login-text { height: 24px; left: 24px; border: 1px solid #e9e9e9; background: #f9f9f9; } .login-text-focus { border: 1px solid #E6BF73; } .login-btn { width: 114px; height: 29px; color: #E9FFFF; line-height: 29px; background: url('/Content/Images/login/login-btn.gif') no-repeat; border: none; overflow: hidden; cursor: pointer; } #txtUsername, #code, #txtPassword { width: 191px; } #logincopyright { text-align: center; color: White; margin-top: 50px; } a { color: Black; } a:hover { color: Red; text-decoration: underline; } </style> </head> <body style="padding: 10px"> <div id="login"> <div id="loginlogo"> </div> <div id="loginpanel"> <div class="panel-h"> </div> <div class="panel-c"> <div class="panel-c-l"> <table cellpadding="0" cellspacing="0"> <tbody> <tr> <td align="left" colspan="2"> <h3> 请使用传智播客CMS系统账号登录 </h3> </td> </tr> <tr> <td align="right"> 账号: </td> <td align="left"> <input type="text" name="LoginCode" id="LoginCode" class="login-text" /> </td> </tr> <tr> <td align="right"> 密码: </td> <td align="left"> <input type="password" name="LoginPwd" id="LoginPwd" value="123" class="login-text" /> </td> </tr> <tr> <td> 验证码: </td> <td align="left"> <input type="text" class="login-text" id="code" name="vCode" value="1" /> </td> </tr> <tr> <td></td> <td> <img id="img" src="/Login/ValidateCode/?id=1" style="float: left; height: 24px;" /> <div style="float: left; margin-left: 5px; margin-top: 10px;"> <a href="javascript:void(0)" onclick="changeCheckCode();return false;">看不清,换一张</a> </div> </td> </tr> <tr> <td align="center" colspan="2"> <input type="submit" id="btnLogin" value="登录" class="login-btn" /> <span id="errorMsg"></span> </td> </tr> </tbody> </table> </div> <div class="panel-c-r"> <p> 请从左侧输入登录账号和密码登录 </p> <p> 如果遇到系统问题,请联系网络管理员。 </p> <p> 如果没有账号,请联系网站管理员。 </p> <p> ...... </p> </div> </div> <div class="panel-f"> </div> </div> <div id="logincopyright"> Copyright ? 2012 Yilian.com </div> </div> </body> </html>
视图中img标签显示验证码,src指向Login控制器中的ValidataCode。
<img id="img" src="/Login/ValidateCode/?id=1" style="float: left; height: 24px;" />
验证码看不清,点击重新生产,jquery更改src的属性就行
function changeCheckCode() { var obj = $("#img").attr("src"); $("#img").attr("src", obj + 1); }
****img,css样式等放入Content文件夹中,easyui,jquery等放在Script文件中中
You are never too old to set another goal or to dream a new dream!!!