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 / 2;
        byte[] inputByteArray = new byte[len];
        int x, i;
        for (x = 0; x < len; x++)
        {
            i = Convert.ToInt32(Text.Substring(x * 2, 2), 16);
            inputByteArray[x] = (byte)i;
        }
        des.Key = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
        des.IV = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
        cs.Write(inputByteArray, 0, 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(0, 8));
        des.IV = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
        cs.Write(inputByteArray, 0, 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 / 2;
        byte[] inputByteArray = new byte[len];
        int x, i;
        for (x = 0; x < len; x++)
        {
            i = Convert.ToInt32(Text.Substring(x * 2, 2), 16);
            inputByteArray[x] = (byte)i;
        }
        des.Key = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
        des.IV = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
        cs.Write(inputByteArray, 0, inputByteArray.Length);
        cs.FlushFinalBlock();
        return Encoding.Default.GetString(ms.ToArray());
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        int codeW = 80;
        int codeH = 22;
        int fontSize = 16;
        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 = { ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘8‘, ‘9‘, ‘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 = 0; i < 4; i++)
        {
            chkCode += character[rnd.Next(character.Length)];
        }
        //Session["yzmCode"] = chkCode;
        HttpCookie cook = new HttpCookie("yzmCode", Encrypt(chkCode));
        cook.Expires = DateTime.Now.AddMinutes(20);
        Response.Cookies.Add(cook);
        Bitmap bmp = new Bitmap(codeW, codeH);
        Graphics g = Graphics.FromImage(bmp);
        g.Clear(Color.White);
        for (int i = 0; i < 1; 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 = 0; 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 * 18 + 2, (float)0);
        }
        for (int i = 0; i < 100; 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(0);
        Response.Expires = 0;
        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();
    }
时间: 2024-12-15 01:38:22

exchange邮箱系统增加验证码机制的相关文章

(二)简单的登陆注册系统--增加验证码部分

login.html <html> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <h1>登陆系统</h1> <form action="login1.php" method="post"> 用户名:<input type="text"  name=&q

Exchange 增加验证码

Exchange增加验证码机制1.1. 需要修改的文件 "logon.aspx" "flogon.js" "logon.css" 路径: %\Program Files\Microsoft\Exchange server\V15\FrontEnd\HttpProxy\owa\auth\15.1.1261\scripts\premium\auth\15.1.1261\themes\resources1.2 首先打开"logon.aspx&

Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的 源代码.细心的读者会发现,这几篇文章分析的Binder接口都是基于C/C++语言来实现的,但是我们在编写应用程序都是基于Java语言的,那么,我 们如何使用Java语言来使用系统的Binder机

自建exchange邮箱怎么发送超大附件?

不少IT经理都遇到过这样的问题:公司自建exchange邮箱,但是大附件如果存到邮件服务器里对服务器负担会比较大,也并没有找到其他靠谱的方法,怎么破? 其实,公司內部使用的邮件系统,如果有超大附件的需求,可私有化部署邮件服务器或选择商业SaaS解决方案.既然自建了Exchange邮箱,且有发送超大附件的需求,可以多备一个存储服务器,有定时清理机制就好了. 自己做附件管理嫌麻烦的话,市场上也有现成的超大附件相关产品和方案.不过既然已经在使用Exchange了,最好选择可集成Exchange的产品进

[转帖]实时流处理系统反压机制(BackPressure)综述

实时流处理系统反压机制(BackPressure)综述 https://blog.csdn.net/qq_21125183/article/details/80708142 2018-06-15 19:05:37 MasterT-J 阅读数 4808更多 分类专栏: 实时流处理 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qq_21125183/article/details/8070

[Spark内核] 第35课:打通 Spark 系统运行内幕机制循环流程

本课主题 打通 Spark 系统运行内幕机制循环流程 引言 通过 DAGScheduelr 面向整个 Job,然后划分成不同的 Stage,Stage 是從后往前划分的,执行的时候是從前往后执行的,每个 Stage 内部有一系列任務,前面有分享過,任务是并行计算啦,这是并行计算的逻辑是完全相同的,只不过是处理的数据不同而已,DAGScheduler 会以 TaskSet 的方式把我们一个 DAG 构造的 Stage 中的所有任务提交给底层的调度器 TaskScheduler,TaskSchedu

利用hadoop1.x集群进行探索性实验(一)【对WEB监控界面增加安全机制】

这个实验我选择了简单的做法,并没有用到kerkeros.本人会努力,尽快学会用到kerkeros给hadoop增加安全机制,使我的小象不再“裸奔”. 首先是打开hdfs-site.xml,然后加入如下属性.最后设置登录用户名.就是在设置hadoop.http.authentication.signature.sercet.file属性时指定的目录文件,在文件中写入用于登录的用户名.我这里填的是leung.登录时在网址后面加上“?user.name=leung”即可访问. 接着启动集群,并且关闭开

JavaScript邮箱系统开发(六)

一.下一个选项卡 //下一个选项卡 $('#J_next').click(function(e) { e.preventDefault(); e.stopPropagation(); var ul = $('#B_history'), current = ul.find('.current'), li = current.next('li'); showTab(li); }); 二.上一个选项卡 //上一个选项卡 $('#J_prev').click(function(e) { e.preven

php实现动态随机验证码机制(CAPTCHA)

php实现动态随机验证码机制 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序.可以防止:恶意破解密码.刷票.论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上用验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能. 这个