exchange邮箱系统增加验证码机制
首先背景是exchange的邮箱系统没有后台源代码。因为这个原因,生成验证码的机制放在aspx的runat="sever"后台代码里面。
首先需要找到iis中logon.aspx文件。在这里找到输入邮箱名和密码的input元素,对应增加上输入验证码的input和显示验证码图片的img元素。
需要增加两个文件:VerifyCode.aspx是用户输入进行输入的验证码验证操作的代码;GetImg.aspx是用于显示验证码图片的,即将之前添加的img的src设置为这个GetImg.aspx即可。至于点击img之后自动刷新,则属于体验性的改进。
代码具体执行逻辑是GetImg在load的时候,将随机生成的验证码加密之后,存在客户端浏览器的cookie中,同时创建一个Img对象,将4位验证码字符按顺序输出到img对象上,同时img随机分布一些点pixel,之后图片的stream返回到浏览器上。
而VerifyCode的验证则是则根据输入的内容和之前的cookie存的密文解密之后进行比较,如果一致,则通过验证。
VerifyCode.aspx代码如下:
<%@ Page Language="C#" AutoEventWireup="true" Debug="true" %> <%@ Import Namespace="System.Security.Cryptography" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (Request.Cookies["yzmCode"] != null && Request.QueryString["yzmc"] != null)
{
string code = Decrypt(Request.Cookies["yzmCode"].Value).ToUpper();
//Response.Write("code"+code+"\n");
//Response.Write("code"+code+"\n");
//Response.End();
string ucode = Request.QueryString["yzmc"].ToUpper();
if (code == ucode)
{
Response.Write("ok");
Response.End();
}
else
{
Response.Write("error");
Response.End();
}
}
else
{
Response.Write("error2");
Response.End();
}
}
public static string Decrypt(string Text)
{
string sKey = "Exchange";
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
int len;
len = Text.Length / ;
byte[] inputByteArray = new byte[len];
int x, i;
for (x = ; x < len; x++)
{
i = Convert.ToInt32(Text.Substring(x * , ), );
inputByteArray[x] = (byte)i;
}
des.Key = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(, ));
des.IV = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(, ));
System.IO.MemoryStream ms = new System.IO.MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, , inputByteArray.Length);
cs.FlushFinalBlock();
return Encoding.Default.GetString(ms.ToArray());
}
</script>
GetImg.aspx代码如下:
<%@ Page Language="C#" AutoEventWireup="true" %> <%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Security.Cryptography" %>
<script runat="server">
public static string Encrypt(string Text)
{
string sKey = "Exchange";
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
byte[] inputByteArray;
inputByteArray = Encoding.Default.GetBytes(Text);
des.Key = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(, ));
des.IV = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(, ));
System.IO.MemoryStream ms = new System.IO.MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, , inputByteArray.Length);
cs.FlushFinalBlock();
StringBuilder ret = new StringBuilder();
foreach (byte b in ms.ToArray())
{
ret.AppendFormat("{0:X2}", b);
}
return ret.ToString();
}
public static string Decrypt(string Text)
{
string sKey = "Exchange";
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
int len;
len = Text.Length / ;
byte[] inputByteArray = new byte[len];
int x, i;
for (x = ; x < len; x++)
{
i = Convert.ToInt32(Text.Substring(x * , ), );
inputByteArray[x] = (byte)i;
}
des.Key = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(, ));
des.IV = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(, ));
System.IO.MemoryStream ms = new System.IO.MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, , inputByteArray.Length);
cs.FlushFinalBlock();
return Encoding.Default.GetString(ms.ToArray());
}
protected void Page_Load(object sender, EventArgs e)
{
int codeW = ;
int codeH = ;
int fontSize = ;
string chkCode = string.Empty;
Color[] color = { Color.Black, Color.Red, Color.Blue, Color.Green, Color.Orange, Color.Brown, Color.Brown, Color.DarkBlue };
string[] font = { "Times New Roman", "Verdana", "Arial", "Gungsuh", "Impact" };
char[] character = { '', '', '', '', '', '', '', 'a', 'b', 'd', 'e', 'f', 'h', 'k', 'm', 'n', 'r', 'x', 'y', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', 'X', 'Y' };
Random rnd = new Random();
for (int i = ; i < ; i++)
{
chkCode += character[rnd.Next(character.Length)];
}
//Session["yzmCode"] = chkCode;
HttpCookie cook = new HttpCookie("yzmCode", Encrypt(chkCode));
cook.Expires = DateTime.Now.AddMinutes();
Response.Cookies.Add(cook);
Bitmap bmp = new Bitmap(codeW, codeH);
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.White);
for (int i = ; i < ; i++)
{
int x1 = rnd.Next(codeW);
int y1 = rnd.Next(codeH);
int x2 = rnd.Next(codeW);
int y2 = rnd.Next(codeH);
Color clr = color[rnd.Next(color.Length)];
g.DrawLine(new Pen(clr), x1, y1, x2, y2);
}
for (int i = ; i < chkCode.Length; i++)
{
string fnt = font[rnd.Next(font.Length)];
Font ft = new Font(fnt, fontSize);
Color clr = color[rnd.Next(color.Length)];
g.DrawString(chkCode[i].ToString(), ft, new SolidBrush(clr), (float)i * + , (float));
}
for (int i = ; i < ; 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);
}
Response.Buffer = true;
Response.ExpiresAbsolute = System.DateTime.Now.AddMilliseconds();
Response.Expires = ;
Response.CacheControl = "no-cache";
Response.AppendHeader("Pragma", "No-Cache");
MemoryStream ms = new MemoryStream();
try
{
bmp.Save(ms, ImageFormat.Png);
Response.ClearContent();
Response.ContentType = "image/Png";
Response.BinaryWrite(ms.ToArray());
}
finally
{
bmp.Dispose();
g.Dispose();
}
}
</script>
注意:加密解密对应的sKey变量要一致。
判断验证码是否输入正确的js逻辑(简单点描述就是发起get请求,地址是上面提到的VerifyCode.aspx,参数和代码中对应上即可):
var codeVaule = $("#yzm").val();
if(codeVaule == ""){
$("#yzm-tip").html("验证码不能为空");
return false;
}else if(codeVaule.length!=4){
$("#yzm-tip").html("验证码位数不正确");
return false;
}else{
$.get("VerifyCode.aspx?yzmc="+codeVaule,{},function(data){
if(data=="ok"){
$("#yzm-tip").html("验证码正确");
//$(".btnSignin").click();
clkLgn();//登录逻辑
bo=true;
}else{
$("#yzm-tip").html("验证码错误!");
}
});
}
return bo;
(为了简单,使用了jquery,引用即可)
触发登录操作的js函数是clkLgn(),这个放在flogon.js这个脚本文件里面,由于存在点击登录按钮和直接回车(e.keyCode == 13)直接执行登录的两种场景,因此此处需要看清js代码。具体倒没什么难度。
可以修改clkLgn()的代码逻辑,直接在里面增加对输入验证码进行验证的逻辑,然后确定是否走真正的登录的代码。也可以在点击登录按钮或者回车的两处逻辑上分别走验证请求再处理。
本身加上验证码的目的只是为了防止密码撞库,快速达到要求即可。
点击验证码图片自动刷新的改进:
function refreshImg(){
$("#yzmImg")[0].src="GetImg.aspx?"+Math.random();
}
exchange邮箱系统增加验证码机制的更多相关文章
- web系统登陆页面增加验证码
传统登陆页面中包含两个输入项: • 用户名 • 密码有时为了防止机器人进行自动登陆操作,或者防止恶意用户进行用户信息扫描,需增加动态验证码功能.此时,登陆页面中包含了三个输入项: • 用户名 • 密码 ...
- Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了A ...
- [转帖]实时流处理系统反压机制(BackPressure)综述
实时流处理系统反压机制(BackPressure)综述 https://blog.csdn.net/qq_21125183/article/details/80708142 2018-06-15 19 ...
- TODO:Laravel增加验证码
TODO:Laravel增加验证码1. 先聊聊验证码是什么,有什么作用?验证码(CAPTCHA)是"Completely Automated Public Turing test to te ...
- (3)MEF插件系统中通信机制的设计和实现
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 一般的WinForm中通过C#自带的Event机制便能很好的实 ...
- yii2增加验证码详细步骤
作者:白狼 出处:http://www.manks.top/article/yii2_captcha本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留 ...
- (原创)AD账户误删导致Exchange邮箱被删 莫苦恼
由于人员变动,离职人员AD账户和邮箱经常要删除.但是在删除AD账户的时候难免会犯错,将在用的用户给删除了,这是个痛苦的事情, 然后你会发现Exchange邮箱也会跟着删除,抓狂了..,还好,幸亏这里进 ...
- sharepoint获取exchange邮箱报错:该帐户无权模拟所请求的用户
现象: sharepoint获取exchange邮箱报错:该帐户无权模拟所请求的用户 处理办法: 1.Open the Exchange Management Shell 2.输入: New-Mana ...
- cas sso单点登录系列5_cas单点登录增加验证码功能完整步骤
转:http://blog.csdn.net/ae6623/article/details/8919718 本篇教程cas-server端下载地址:解压后,直接放到tomcat的webapp目录下就能 ...
随机推荐
- C# 将Dictionary,StringDictionary等集合数据绑定到如comboBox等控件数据源中将获取健值
一般在使用C#提供的如combobx控件绑定数据源时都是直接绑定数据库里的数据的(DataTable,DataSet等) 最近在一个项目里需要使用combobox绑定类似“状态的”数据源,该字段里的数 ...
- RS报表自动适应屏幕分辨率大小
问题:同一个报表,由于用户电脑显示器大小,分辨率大小不同显示的不一样,看起来不完整或者很不协调 原因:设计报表大小属性的时候使用了固定值属性,比如限制为宽:1200px 那么在电脑屏幕小分辨率很小的情 ...
- github 排名前100的项目
dotnet/roslyn The .NET Compiler Platform ("Roslyn") provides open-source C# and Visual Bas ...
- C#基础视频教程6.2 如何简单读写数据库
上一节我们简单介绍了数据库的读写,所使用的数据库都是随便写的(用水果代替,但不是真正的食品零售数据表,至少没有价格,销量等等).这一节我们思考如何实现一个测试题的数据库,所谓的测试题数据库就是假定系统 ...
- 在mvc4里怎样引用:System.Web.Optimization和entityframework
请在nuget 里运行: Install-Package Microsoft.AspNet.Web.Optimizationinstall-package entityframework
- 基于swiper的移动端H5页面,丰富的动画效果
概述 通过运用swiper插件,制作移动端上下整屏滑动的H5页面,用来宣传或者简单注册等,可以嵌套H5音乐或者视频. 详细 代码下载:http://www.demodashi.com/demo/119 ...
- AI:人工智能搜索策略
人工智能搜索策略:
- 简述document.write和 innerHTML的区别。
document.write是重写整个document, 写入内容是字符串的htmlinnerHTML是HTMLElement的属性,是一个元素的内部html内容
- centos下 安装jdk
JDK 1.7下载地址 http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html JDK ...
- C#中byte类型转换为double类型
// Initialize unmanged memory to hold the array. int size = Marshal.SizeOf(bytes[0]) * bytes.Length; ...