设为首页 收藏本站
查看: 4070|回复: 6

[经验分享] Exchange邮箱登陆界面添加验证码功能完美解决方案

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2013-9-13 09:49:24 | 显示全部楼层 |阅读模式
前言:
   昨天思路错误,白忙了一上午因为Exchange安装好之后是依附于IIS的所以我们看到登陆界面也是个.aspx页面 通过IIS找到的Exchange安装目录发现只有logon.aspx页面 没有也不可能有logon.aspx.cs页面,说白了就是微软给咱们写好了一个(一套)软件--Exchange邮件服务系统,对于用户,亲你只需要安装就行了。。。
后语:
   这意味着exchange走的也是IIS,也是asp.net那一套流程,ok 需求来了:

   上帝:我想要在邮箱登陆的时候加一个验证码的功能,这样不是会更安全嘛。

   开发者:额,好吧。。。(心说,尼玛坑爹呐,这是微软写好的我怎么给你加验证码呀!!)

儿子就算是在坑爹,那也是咱儿子啊,满足不了他到时候认贼作父就不好了。
   说了半天废话咱们奔主题吧。。。。。。。。

主题:
   既然我们能看到Exchange安装好部署后的页面能对于前端来讲我们还是可以改变的,思路有一下3种:

   1)网上案例:

   请看这位大神的示例代码,但因为时间有点久远了,相关Code下载不过来,不过有兴趣的还是可以看看的。

   2)前端验证

顾名思义,就是使用js来在前端动态生成验证功能,控制用户登录

       缺点:这只是表面的现象,一旦有高手察觉这个验证功能只是张纸那么薄,很容易捅破。

   demo:效果如下
133947902.jpg




<html xmlns="http://www.w3.org/1999/xhtml" ><head>    <title>无标题页</title>    <style type="text/css">        .code        {            background-image:url(code.jpg);            font-family:Arial;            font-style:italic;            color:Red;            border:0;            padding:2px 3px;            letter-spacing:3px;            font-weight:bolder;        }        .unchanged        {            border:0;        }    </style>    <script language="javascript" type="text/javascript">        var code; //在全局 定义验证码        function createCode() {            code = "";            var codeLength = 6;//验证码的长度            var checkCode = document.getElementById("checkCode");            var selectChar = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');//所有候选组成验证码的字符,当然也可以用中文的            for (var i = 0; i < codeLength; i++) {                var charIndex = Math.floor(Math.random() * 36);                code += selectChar[charIndex];            }            //       alert(code);            if (checkCode) {                checkCode.className = "code";                checkCode.value = code;            }        }        function validate() {            var inputCode = document.getElementById("input1").value;            if (inputCode.length <= 0) {                alert("请输入验证码!");            }            else if (inputCode.toUpperCase() != code.toUpperCase()) {                alert("验证码输入错误!");                createCode();//刷新验证码            }            else {                alert("^-^ OK");            }        }    </script></head><body     <form  action="#">        <table>            <tr><td>姓 名:</td><td><input type="text" style="width: 160px;"/></td></tr>            <tr><td>密 码:</td><td><input type="password" style="width: 160px;"/></td></tr>            <tr><td>验证码:</td><td><input  type="text" style="width: 160px;"  id="input1" />        <input type="text"  readonly="readonly" id="checkCode" class="unchanged" style="width: 80px"  /></td></tr>        <tr><td></td><td><input id="Button1"   type="button" value="确定" />   </td></tr>        </table>                                                                                                                                                                                                                                                                                                                                                   </form></body></html>
虽然每次点击验证码的时候会发生变动,但是这个验证码不是图片,所以还是有程序可以注入的,比如下边这种也是 134535101.jpg
亲你懂了吧~~~~~~~
   3)后端伪验证:

   哎,为什么要加个“伪”呐因为如果不是js你也没办法阻止表单的提交,而且表单提交后也没有什么验证,就是在验证用户登录的时候你是没办法拦截用户的登录信息提取验证码的

   缺点:类似前端js 验证

demo:先上效果图:
135115470.jpg
废话不多说了,贴出流程:
在IIS中找到Exchange登录界面页面的物理路径,找到页面logon.aspx,添加如下代码:
12345<!----------------------------------------------------------- start 验证码 ---------------------------------------------------------------------><tr><td nowrap><label for="yzm">验证码:</label></td><td class="txtpad"><input type='text'class='txt' maxlength="4" style="width:220px;" id='yzm' /><img src='GetImg.aspx'   alt="点击切换验证码" title="点击切换验证码" style=" margin-top:2px; vertical-align:top;cursor:pointer;"  'GetImg.aspx');return false;" /></td></tr>    <!----------------------------------------------------------- end 验证码 --------------------------------------------------------------------->你懂得,具体位置有你定,然后加入以下js代码(这个位置随意):
<!------------------------------------------ 验证码 脚本 ------------------------------------------------------------><script type="text/javascript"  src=\'#\'" /script><script type="text/javascript">function ToggleCode(obj, codeurl) {    $(obj).attr("src", codeurl + "?time=" + Math.random());}var bo=false;$(document).ready(function(){    $(".btn").before("<label id='spanMsg' style='color:red;padding-right:50px;'> </label>");    $(".btn").click(function(){       if(bo){          return true;       }else{        var codeVaule=$("#yzm").val();        if(codeVaule==""){            $("#spanMsg").html("*验证码不能为空!");            return false;        }else if(codeVaule.length!=4){            $("#spanMsg").html("*验证码位数不够!");            return false;        }else{            $.get("VerifyCode.aspx?yzmc="+codeVaule,{},function(data){                if(data=="ok"){                    $("#spanMsg").html("*验证码正确!");                    $(".btn").click();                    bo=true;                }else{                    $("#spanMsg").html("*验证码错误!");                }            });        }        return bo;        }                                                                                                                                                                                               });});</script><!------------------------------------------- end 验证码 脚本 ----------------------------------------------------------->然后在logon.aspx同一目录下添加jquery-1.7.1.min.js文件具体是什么版本的jquery你可以任意选择,应该都能兼容。注意js代码的引用名称一致。然后添加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 = "nysoftland.com.cn";        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.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>在第72行的时候不适用session验证,因为Exchange安装后使用的不是Session验证机制,所以我们在73~75行采用Cookies验证机制。以上代码用于生成验证码。下边采用jquery异步验证机制验证 验证码填写是否正确,同样添加VerifyCode.aspx文件代码如下:
<%@ Page Language="C#" AutoEventWireup="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();            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>



到此我们的代码就已经填写完毕了

总结:
   有很好的asp.net底层基础遇到问题还是能解决的挺顺手的。不过说白了这些都是表面现象,你无法重写Exchange编译好的dll,也就是说想绕过你的验证还是很容易的,这些都只是忽悠用户拔了,如果想更安全就要修改IIS,在Exchange登录时再包装一层是用户无法绕过验证码的验证,只不过本次需求不需要这么高的安全性,能用好看就行...

   欢迎诸位大神拍砖。。。。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-9247-1-1.html 上篇帖子: exchange server 2010 证书安装、使用 下篇帖子: Exchange 2010 SP1的OWA中无法删除邮件 验证码 解决方案 邮箱登陆

尚未签到

发表于 2013-9-17 11:08:33 | 显示全部楼层
有事秘书干,没事干秘书!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

尚未签到

发表于 2013-9-21 17:20:20 | 显示全部楼层
人生不能像做菜、把所有的料都准备好才下锅!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

尚未签到

发表于 2013-9-23 03:23:42 | 显示全部楼层
看尽天下A片,心中自然无码~

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

尚未签到

发表于 2013-9-24 06:19:55 | 显示全部楼层
路过,支持一下啦

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

尚未签到

发表于 2013-9-25 11:07:47 | 显示全部楼层
女,喜甜食,甚胖!该女有一癖好:痛恨蚂蚁,见必杀之。问其故曰:这小东西,那么爱吃甜食,腰还那么细!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

尚未签到

发表于 2013-9-27 04:36:29 | 显示全部楼层
看帖回帖是美德!:lol

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表