[转]大流量、高并发网站验证码解决方案

原文地址: 

http://www.oksvn.com/Article/Detail-71.shtml

 

摘录: 

大型站点都是把验证码服务器和应用服务器分开的。具体的做法有两种:

1.获取验证码的时候验证码服务器往客户端写验证cookies,提交的时候服务端获取这个cookie和提交上来的验证码,再去验证码服务器验证。

2.获取验证码的时候传个应用这边的session到验证码服务器那边,提交的时候服务端把应用这边的session和提交上来的验证码一起到验证码服务器验证。

  

实现例子:

首先要解决的一个问题就是怎么样把客户端请求的验证码数据存储起来而且要两边都能够访问我是这样解决的:

ExpandedBlockStart.gif 代码
using  System;
using  System.Configuration;
using  System.Collections;
using  System.Collections.Generic;
using  System.Text;

namespace  Flyimg.Verify.Server
{
    
public   class  CodeSession
    {
        
///   <summary>
        
///  存放验证数据链表
        
///   </summary>
         private   static  LinkedList < CodeSession >  VerifyCodeList  =   new  LinkedList < CodeSession > ();

        
private   string  _SessionId;
        
private   string  _VerifyCode;

        
///   <summary>
        
///  构造函数
        
///   </summary>
        
///   <param name="strSessionId"></param>
        
///   <param name="strVerifyCode"></param>
         public  CodeSession( string  strSessionId,  string  strVerifyCode)
        {
            _SessionId 
=  strSessionId;
            _VerifyCode 
=  strVerifyCode;
        }

        
///   <summary>
        
///  添加验证码数据
        
///   </summary>
        
///   <param name="strSessionId"></param>
        
///   <param name="strVerifyCode"></param>
        
///   <returns></returns>
         public   static   string  Add( string  strSessionId,  string  strVerifyCode)
        {
            
bool  bResult  =   false ;

            LinkedListNode
< CodeSession >  CurrentPlay  =   new  LinkedListNode < CodeSession > ( new  CodeSession(strSessionId, strVerifyCode));

            
try
            {
                
// 保持链表长度限制客户端连接数
                 if  (VerifyCodeList.Count  <   int .Parse(ConfigurationManager.AppSettings[ " Capacity " ].ToString()))
                {
                    VerifyCodeList.AddFirst(CurrentPlay);
                }
                
else
                {
                    VerifyCodeList.RemoveLast();
                    VerifyCodeList.AddFirst(CurrentPlay);
                }
                bResult 
=   true ;
            }
            
catch
            {
                bResult 
=   false ;
            }

            
return  bResult.ToString();
        }

        
///   <summary>
        
///  删除验证码数据
        
///   </summary>
        
///   <param name="strSessionId"></param>
        
///   <param name="strVerifyCode"></param>
         public   static   void  Remove( string  strSessionId,  string  strVerifyCode)
        {
            CodeSession codesession 
=   new  CodeSession(strSessionId, strVerifyCode);
            VerifyCodeList.Remove(codesession);
        }

        
///   <summary>
        
///  验证验证码数据
        
///   </summary>
        
///   <param name="strSessionId"></param>
        
///   <param name="strVerifyCode"></param>
        
///   <returns></returns>
         public   static   string  Verify( string  strSessionId,  string  strVerifyCode)
        {
            
int  iResult  =   0 ;

            
foreach  (CodeSession codesession  in  VerifyCodeList)
            {
                
if  (codesession._SessionId  ==  strSessionId  &&  codesession._VerifyCode  ==  strVerifyCode)
                {
                    iResult 
=   1 ;
                    Remove(strSessionId, strVerifyCode);
                    
break ;
                }
            }

            
return  iResult.ToString();
        }

        
///   <summary>
        
///  清除验证数据
        
///   </summary>
         public   static   void  Clear()
        {
            VerifyCodeList.Clear();
        }
    }
}

 

有两个主要的方法,ADD(添加)和Verify(验证)还有个问题就是两边的应用能快速的访问这个区域。我采用的是socket

没有采用webservice的原因的这样既可以分布式的部署而且速度够快。在验证码web端配置文件中配置好验证码Server的IP地址就可以了。

在验证码web端获取到验证码数据后:

ExpandedBlockStart.gif 代码
try
{
    
// 添加验证到验证服务器
    Common.AddToVerifyServer(Session.SessionID,  this .strVerifyCode);
}
catch  (Exception ex)
{
    Logger.Add(ex.Message);
}

// 写cookie
General.SetCookie( " VerifyKey " , Session.SessionID,  " flyimg.cn " );

 

 

这样验证码web端的任务就完成了,验证码Server中就有数据显示了:

提交的时候:

 

ExpandedBlockStart.gif 代码
protected   override   void  OnPostting(Object sender, DataEventArgs e)
{
    
if  ( string .IsNullOrEmpty(Request.Form[ " UserAccounts " ]))
    {
    strError1 
=   " 请输入用户名! " ;
    }
    
else   if  ( string .IsNullOrEmpty(Request.Form[ " UserPwd " ]))
    {
    strError2 
=   " 请输入密  码! " ;
    }
    
else   if  ( string .IsNullOrEmpty(Request.Form[ " VerifyCode " ]))
    {
    strError3 
=   " 请输入验证玛! " ;
    }
    
else
    {
    
bool  bResult  =   false ;

    
try  
        {            
        
// 到验证服务器验证
        bResult  =  Common.Verify(ToolKit.Common.General.GetCookie( " VerifyKey " ), Request.Form[ " VerifyCode " ]);
        }
        
catch  (Exception ex)
        {
        Logger.Add(ex);
        }

    
if  (bResult)
    {
        
if  (Request.Form[ " UserAccounts " ==   " admin "   &&  Request.Form[ " UserPwd " ==   " 123123 " )
        {
        General.SetCookie(
" user_id " " admin " );

        
string  strReturnUrl  =  Request.QueryString[ " url " ];

        
if  ( ! string .IsNullOrEmpty(strReturnUrl))
        {
            Response.Redirect(HttpUtility.UrlDecode(Request.QueryString[
" url " ]));
        }
        
else
        {
            Response.Redirect(
" /upload " );
        }
        }
        
else
        {
        strError2 
=   " 用户名或者密码错误! " ;
        }
    }
    
else
    {
        strError3 
=   " 验证玛错误! " ;
    }
    }
}

 

好了。功能就是这样实现的。这是用第一种方式实现的,稍微修改下就可以改成第二种方式了。

下载地址:http://www.svnhost.cn/Download/Detail-108.shtml

Server端用到了一个开源的Socket类库Midapex.Net:

http://www.cnblogs.com/dyj057/archive/2008/04/18/1160392.html

谢谢,欢迎大家交流!enjoy... 

 

 

 

转载于:https://www.cnblogs.com/DrWang/archive/2010/10/18/1854505.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值