惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
K
Kaspersky official blog
L
LangChain Blog
有赞技术团队
有赞技术团队
V
Visual Studio Blog
T
The Blog of Author Tim Ferriss
Microsoft Azure Blog
Microsoft Azure Blog
Stack Overflow Blog
Stack Overflow Blog
美团技术团队
Vercel News
Vercel News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
G
Google Developers Blog
宝玉的分享
宝玉的分享
月光博客
月光博客
爱范儿
爱范儿
The Register - Security
The Register - Security
S
SegmentFault 最新的问题
M
MIT News - Artificial intelligence
F
Full Disclosure
Engineering at Meta
Engineering at Meta
阮一峰的网络日志
阮一峰的网络日志
Hugging Face - Blog
Hugging Face - Blog
A
About on SuperTechFans
WordPress大学
WordPress大学
D
Docker
Y
Y Combinator Blog
N
News and Events Feed by Topic
P
Proofpoint News Feed
Apple Machine Learning Research
Apple Machine Learning Research
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Recorded Future
Recorded Future
IT之家
IT之家
C
CXSECURITY Database RSS Feed - CXSecurity.com
Security Latest
Security Latest
Spread Privacy
Spread Privacy
D
Darknet – Hacking Tools, Hacker News & Cyber Security
F
Fortinet All Blogs
AWS News Blog
AWS News Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
D
DataBreaches.Net
Recent Announcements
Recent Announcements
博客园 - Franky
Google DeepMind News
Google DeepMind News
小众软件
小众软件
B
Blog RSS Feed
I
InfoQ
Attack and Defense Labs
Attack and Defense Labs
云风的 BLOG
云风的 BLOG

博客园 - Dr.Wang

mongoDB操作命令,摘自官方helper 让PDF文件也支持书签功能 编码简介 [转]C# 的readonly和const区别 [转]截获asp.net http输出流自己做处理 [转]DES加密 java与.net可以相互加密解密两种方法 [转]JAVA与.NET DES加密解密 Ext树控件的制作 [转]SqlServer行列倒置示例 [转]url传递中文的解决方案总结 - Dr.Wang - 博客园 [转]正则表达式基础知识 - Dr.Wang - 博客园 [转]揭开正则表达式的神秘面纱 [转]正则表达式30分钟入门教程 [转]通用分页存储过程 [转]sqlserver2005分页查询 匿名方法解决多线程访问控件的问题 - Dr.Wang - 博客园 [转载]C#自定义事件的步骤介绍 [转载]UDP数据包穿透NAT [转载]UDP数据包大小问题
[转]大流量、高并发网站验证码解决方案
Dr.Wang · 2010-10-18 · via 博客园 - Dr.Wang

原文地址: 

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

摘录: 

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

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

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

实现例子:

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

代码

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端获取到验证码数据后:

代码

try
{
    
//添加验证到验证服务器
    Common.AddToVerifyServer(Session.SessionID, this.strVerifyCode);
}
catch (Exception ex)
{
    Logger.Add(ex.Message);
}
//写cookie
General.SetCookie("VerifyKey", Session.SessionID, "flyimg.cn");

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

提交的时候:

代码

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...