好几个小时没搞定,MVC中同一页面两个验证码相同的问题

lovebaby 2015-11-24 11:57:07
测试VIEW很简单,代码如下:

<img src="/register/GetValidateCode?type=mail&abc=0.23153452345" />
<img src="/register/GetValidateCode?type=phone&abc=0.4567457648678" />


对应Action
        public ActionResult GetValidateCode(string type)
{
if (type == "mail")
{
mengma.AppCode.ValidateCode v = new mengma.AppCode.ValidateCode();
1 string code = v.CreateVerifyCode();
2 Response.Cookies["MailChkCode"].Value = code.ToLower();
byte[] bytes = v.CreateImageOnPage(code);
return File(bytes, @"image/jpeg");
}
if (type == "phone")
{
mengma.AppCode.ValidateCode v = new mengma.AppCode.ValidateCode();
3 string code = v.CreateVerifyCode();
4 Response.Cookies["PhoneChkCode"].Value = code.ToLower();
byte[] bytes = v.CreateImageOnPage(code);
return File(bytes, @"image/jpeg");
}
return null;
}


头疼点:

1、调用顺序不固定,通过断点查看也不能确定,生成的两个验证码,有时相同,有时不同,相同机率大概20%。
2、有时调用顺序按1、2、3、4的顺序执行,有时调用顺序按1、3、2、4的顺序执行。行号在对应Action中已标。

随机码函数
public string CreateVerifyCode(int codeLen)
{
if (codeLen == 0)
{
codeLen = Length;
}

string[] arr = CodeSerial.Split(',');

string code = "";

int randValue = -1;

Random rand = new Random(unchecked((int)DateTime.Now.Ticks));

for (int i = 0; i < codeLen; i++)
{
randValue = rand.Next(0, arr.Length - 1);

code += arr[randValue];
}

return code;
}
...全文
262 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
minjunjie 2017-02-04
  • 打赏
  • 举报
回复
问题解决了就不管了啊,说下原因啊。我也是有同类问题才搜索到你这里,只告诉大家已解决却不告诉原因。。。还是说下吧。
lovebaby 2015-11-28
  • 打赏
  • 举报
回复
问题解决,结贴。
lovebaby 2015-11-24
  • 打赏
  • 举报
回复
更正:上面的只是为了方便测试手写了两个不同的随机数
lovebaby 2015-11-24
  • 打赏
  • 举报
回复
引用 2 楼 net_xiaojian 的回复:
url后面加上一个参数:flag=new date() 或者 flag=Math.random()
早都试过了,随机数在一开始就有,上面的只是为了测试手机了两个不同的随机数。
$(function () {
            $("#code").attr("src", "/register/GetValidateCode?type=mail&abc=" + Math.random());
            console.log(Math.random());
            $("#phonecode").attr("src", "/register/GetValidateCode?type=phone&abc=" + Math.random());
            console.log(Math.random());
        });
net_xiaojian 2015-11-24
  • 打赏
  • 举报
回复
url后面加上一个参数:flag=new date() 或者 flag=Math.random()
lovebaby 2015-11-24
  • 打赏
  • 举报
回复
还是上面随机函数和验证码图片的实现,以webform方式,同一页面调用两次aspx页面,就不存在这个问题。可能和MVC的执行方式有关。 我测试过把Action和验证码图片类分成两个,分别不同调用,居然还是会有相同的情况。晕了。
        public ActionResult GetValidateCodeByMail(string type)
        {
            mengma.AppCode.ValidateCodeByMail v = new mengma.AppCode.ValidateCodeByMail();         //把类复制成了两个类,ByMail和ByPhone
            string code = v.CreateVerifyCode();
            Response.Cookies["MailChkCode"].Value = code.ToLower();
            byte[] bytes = v.CreateImageOnPage(code);
            return File(bytes, @"image/jpeg");
        }

        public ActionResult GetValidateCodeByPhone(string type)
        {
            mengma.AppCode.ValidateCodeByPhone v = new mengma.AppCode.ValidateCodeByPhone();        //把类复制成了两个类,ByMail和ByPhone
            string code = v.CreateVerifyCode();
            Response.Cookies["PhoneChkCode"].Value = code.ToLower();
            byte[] bytes = v.CreateImageOnPage(code);
            return File(bytes, @"image/jpeg");
        }
lovebaby 2015-11-24
  • 打赏
  • 举报
回复
我用MVC3新建了一个空项目,然后把验证码类加进去,在默认的Index视图上调用,结果发现了一个很奇怪的现象。 如果我把Layout = "~/Views/Shared/_Layout.cshtml"注释掉,即不用默认的HTML结构,页面中只放两个img,那么每次生成的验证码必定是相同的(刷新时间间隔在一秒左右),连生成图片样式都相同,反之如果不注释,引用默认的JS/CSS,则会生成不同的验证码,至于是否还有相同,倒没测出来。 这个现象的原因是什么,有谁能解释一下么?难道和加载东西的多少有关? 我把测试源代码打了个包,放了一个地址,有兴趣的可以下载自行测试。 http://files.cnblogs.com/files/superfeeling/project.rar
absolutelyaa 2015-11-24
  • 打赏
  • 举报
回复
引用 1 楼 xiaojie_cp 的回复:
还是上面随机函数和验证码图片的实现,以webform方式,同一页面调用两次aspx页面,就不存在这个问题。可能和MVC的执行方式有关。 我测试过把Action和验证码图片类分成两个,分别不同调用,居然还是会有相同的情况。晕了。
        public ActionResult GetValidateCodeByMail(string type)
        {
            mengma.AppCode.ValidateCodeByMail v = new mengma.AppCode.ValidateCodeByMail();         //把类复制成了两个类,ByMail和ByPhone
            string code = v.CreateVerifyCode();
            Response.Cookies["MailChkCode"].Value = code.ToLower();
            byte[] bytes = v.CreateImageOnPage(code);
            return File(bytes, @"image/jpeg");
        }

        public ActionResult GetValidateCodeByPhone(string type)
        {
            mengma.AppCode.ValidateCodeByPhone v = new mengma.AppCode.ValidateCodeByPhone();        //把类复制成了两个类,ByMail和ByPhone
            string code = v.CreateVerifyCode();
            Response.Cookies["PhoneChkCode"].Value = code.ToLower();
            byte[] bytes = v.CreateImageOnPage(code);
            return File(bytes, @"image/jpeg");
        }
Random rand = new Random(unchecked((int)DateTime.Now.Ticks)); 随机数种子用同一个,定义成静态变量 就好,不然并发时,随机数是一样的
BitCoffee 2015-11-24
  • 打赏
  • 举报
回复
引用 9 楼 xiaojie_cp 的回复:
[quote=引用 5 楼 BitCoffee 的回复:] Random rand = new Random(unchecked((int)DateTime.Now.Ticks)); 提取到函数外面试试。
也是不行啊,只要不是频繁刷新,每次产生的结果都是一样的。 [/quote]

Random rand = new Random(unchecked((int)DateTime.Now.Ticks));
public ActionResult GetValidateCode(string type)
        {
            ......
        }
这样不行吗?
lovebaby 2015-11-24
  • 打赏
  • 举报
回复
引用 10 楼 starfd 的回复:
那就从源头改吧,遵循http协议,然后在返回验证码的功能部分加上response.cache.nostore,指定当前返回内容浏览器不要进行缓存
有时间试试吧,针对这块做一个小的单元测试。
jingguoqingzn 2015-11-24
  • 打赏
  • 举报
回复
不清楚,坐等
  • 打赏
  • 举报
回复
那就从源头改吧,遵循http协议,然后在返回验证码的功能部分加上response.cache.nostore,指定当前返回内容浏览器不要进行缓存
lovebaby 2015-11-24
  • 打赏
  • 举报
回复
引用 5 楼 BitCoffee 的回复:
Random rand = new Random(unchecked((int)DateTime.Now.Ticks)); 提取到函数外面试试。
也是不行啊,只要不是频繁刷新,每次产生的结果都是一样的。
public ActionResult GetValidateCode(string type)
        {
            string CodeSerial = "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,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";
            if (type == "mail")
            {
                mengma.AppCode.ValidateCode v = new mengma.AppCode.ValidateCode();
                string[] arr = CodeSerial.Split(',');

                string code = "";

                int randValue = -1;

                Random rand = new Random(unchecked((int)DateTime.Now.Ticks));

                for (int i = 0; i < 4; i++)
                {
                    randValue = rand.Next(0, arr.Length - 1);

                    code += arr[randValue];
                }

                Response.Cookies["MailChkCode"].Value = code.ToLower();
                byte[] bytes = v.CreateImageOnPage(code);
                return File(bytes, @"image/jpeg");
            }
            if (type == "phone")
            {
                mengma.AppCode.ValidateCode v = new mengma.AppCode.ValidateCode();
                string[] arr = CodeSerial.Split(',');

                string code = "";

                int randValue = -1;

                Random rand = new Random(unchecked((int)DateTime.Now.Ticks));

                for (int i = 0; i < 4; i++)
                {
                    randValue = rand.Next(0, arr.Length - 1);

                    code += arr[randValue];
                }

                Response.Cookies["PhoneChkCode"].Value = code.ToLower();
                byte[] bytes = v.CreateImageOnPage(code);
                return File(bytes, @"image/jpeg");
            }
            return null;
        }
lovebaby 2015-11-24
  • 打赏
  • 举报
回复
引用 7 楼 rayyu1989 的回复:
new Random 申明成static, 不要一直new 相同ticks new出来的 很可能产生相同随机数
static重复机率更大。
rayyu1989 2015-11-24
  • 打赏
  • 举报
回复
new Random 申明成static, 不要一直new 相同ticks new出来的 很可能产生相同随机数
正怒月神 版主 2015-11-24
  • 打赏
  • 举报
回复
引用 5 楼 BitCoffee 的回复:
Random rand = new Random(unchecked((int)DateTime.Now.Ticks)); 提取到函数外面试试。
#5观点正解 是的,Random rand = new Random(unchecked((int)DateTime.Now.Ticks)); 作为全局变量应该就可以了
BitCoffee 2015-11-24
  • 打赏
  • 举报
回复
Random rand = new Random(unchecked((int)DateTime.Now.Ticks)); 提取到函数外面试试。

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧