c#实现简单Token口令验证

简介:   最近一个项目发现手机验证码总是被人盗刷,一秒钟刷了1百多个,很明显这种行为是通过软件自动提交的,自动发帖机原理类似,解决这个问题目前有两个方案。  出现这个问题原因:请求手机验证码Api时没有任何带任何验证,只要请求了手机号正确就执行发送操作,软件或代码很容易伪造请求过程。  解决方案有很多种,可以选择下面一种或几种组合起来使用。  方案1:用户获取手机验证码时候弹出图片验证码,输入后再发送。

  最近一个项目发现手机验证码总是被人盗刷,一秒钟刷了1百多个,很明显这种行为是通过软件自动提交的,自动发帖机原理类似,解决这个问题目前有两个方案。

  出现这个问题原因:请求手机验证码Api时没有任何带任何验证,只要请求了手机号正确就执行发送操作,软件或代码很容易伪造请求过程。

  解决方案有很多种,可以选择下面一种或几种组合起来使用。

  方案1:用户获取手机验证码时候弹出图片验证码,输入后再发送。

  优点:增加伪造请求成功的难度,必须输入验证码才可以发送,如果是软件,软件需要有图片验证码识别功能。

  缺点:用户体验不好,增加了普通用户的操作步骤。

  方案2:增加ip黑名单,即检测请求ip的发送频率,如同一个ip一分钟内请求多少次后屏蔽ip。

  缺点:一些软件有主动更换ip的功能,这种方式效果不是很好。

  方案3:加上token口令验证

  在Api中增加口令验证,即每次请求必须带上token,token验证正确了才执行发送操作。

  这个方案为了替代方案1,因为有的公司对前端体验要求极高,增加用户操作步骤后用户体验不好。

  这里token可以放在数据库中,也可以放在内存中,个人建议放在内存中,速度快,查询快,至于冗余的问题,可以增加一个BuildDate来保存生成时间。

  Token描述类

  public class TokenDescriptor

  {

  ///

  /// 客户端唯一Id,必须保证唯一性

  ///

  public string ClientId { get; set; }

  ///

  /// token

  ///

  public string Token { get; set; }

  ///

  /// token生成日期

  ///

  public DateTime BuildDate { get; set; }

  }

  token处理类

  public class TokenFactoryBLL

  {

  private string _ClientId;

  private static List _TokenList;

  static TokenFactoryBLL()

  {

  _TokenList=new List();

  }

  ///

  ///

  ///

  ///
  public TokenFactoryBLL(HttpRequestBase httpRequestBase)

  {

  _ClientId=StringHelper.ClientId(httpRequestBase);

  ClearExpired();

  }

  ///

  /// 可用于远程api

  ///

  ///
  public TokenFactoryBLL(string clientId)

  {

  _ClientId=clientId;

  ClearExpired();

  }

  ///

  /// 生成口令

  ///

  public string Get()

  {

  if (string.IsNullOrEmpty(_ClientId))

  {

  return null;

  }

  string token=Guid.NewGuid().ToString("N");//guid;

  TokenDescriptor tokenDescriptor=new TokenDescriptor();

  tokenDescriptor.ClientId=_ClientId;

  tokenDescriptor.Token=StringHelper.NewGuid();

  tokenDescriptor.BuildDate=Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

  _TokenList.Add(tokenDescriptor);

  return token;

  }

  ///

  /// 验证token

  ///

  ///
  ///

  public TipsInfo Validate(string token)

  {

  TipsInfo tipsInfo=new TipsInfo();

  if (!_TokenList.Exists(c=> c.ClientId.Equals(_ClientId, StringComparison.OrdinalIgnoreCase) && c.Token.Equals(token, StringComparison.OrdinalIgnoreCase)))

  {

  tipsInfo.State=0;

  tipsInfo.Msg="token口令验证失败";

  }

  return tipsInfo;

  }

  ///

  /// 移除对应客户端的所有token

  ///

  ///
  public void Remove()

  {

  _TokenList.RemoveAll(c=> c.ClientId.Equals(_ClientId, StringComparison.OrdinalIgnoreCase));

  }

  ///

  /// 清理过期的token,过期时间10分钟

  ///

  private static void ClearExpired()

  {

  for (var i=0; i < _TokenList.Count; i++)

  {

  TokenDescriptor item=_TokenList[i];

  DateTime startTime=item.BuildDate;

  DateTime endTime=Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

  TimeSpan ts=endTime - startTime;

  int minutes=ts.Minutes;

  if (minutes>10)

  {

  _TokenList.RemoveAt(i);

  }

  }

  }

  }

  附上Helper工具类中clientId的方法:

  ///

  /// 获取并生成客户端唯一Id,保存在cookie中;

  ///

  ///

  public static string ClientId(HttpRequestBase request) //获取客户端唯一Id

  {

  if (request==null)

  {

  return null;

  }

  string clientId=CookieHelper.Get("_clientId_");

  if (string.IsNullOrEmpty(clientId))

  {

  string guid=Guid.NewGuid().ToString("N");//guid

  string ip=StringHelper.GetClientIP().ToString().Replace(".", "").Replace(":", "");

  clientId=guid + ip;

  CookieHelper.Add("_clientId_", clientId);

  }

  return clientId;

  }

  ///

  /// 获取客户端ip

  ///

  ///

  public static string GetClientIP()

  {

  if (System.Web.HttpContext.Current==null) return "127.0.0.1";

  string clientIp=System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

  if (string.IsNullOrEmpty(clientIp))

  {

  clientIp=System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

  }

  if (string.IsNullOrEmpty(clientIp))

  {

  clientIp=System.Web.HttpContext.Current.Request.UserHostAddress;

  }

  if (clientIp.IndexOf(",") > 0)

  {

  clientIp=clientIp.Split(',')[0];

  }

  if (!StringHelper.IsIp(clientIp))

  {

  clientIp="127.0.0.1";

  }

  return clientIp;

  }

  前端发送方式需要更改,在请求手机验证码的api之前,先第一次请求二手QQ卖号平台获取token,然后带上token验证通过后后再请求api。

  这个方案肯定没有验证码的防护效果好,只是增加了伪造请求的步骤,因为现在很多模拟请求的软件都是一次性请求,所以还是能防护大部分的软件。

目录
相关文章
|
消息中间件 Java API
阿里云微服务消息队列Token C# 设备端示例Demo
微消息队列 MQTT 版的客户端收发消息时,服务端会根据 MQTT 客户端设置的 Username 和 Password 参数来进行鉴权。目前支持ak,sk通过签名方式认证,也支持通过Token方式进行认证。本文主要介绍基于:Token 使用NET SDK进行设备端连接认证。
1649 0
阿里云微服务消息队列Token C# 设备端示例Demo
|
消息中间件 Java API
阿里云微服务消息队列Token C# Code Sample
文本主要演示使用C# SDK调用 ApplyToken 创建临时访问 Token。
1040 0
阿里云微服务消息队列Token C# Code Sample
|
Web App开发 JSON C#
JSON WEB TOKEN,简单谈谈TOKEN的使用及在C#中的实现
十年河东,十年河西,莫欺少年穷。 学无止境,精益求精。 突然发现整个十月份自己还没有写一篇博客......哎,说出来都是泪啊,最近加班实在实在实在是太多了,真的没有多余的时间写博客。这不,今天也在加班中...索性,利用加班的一些时间写篇博客吧! 首先说下什么是 JWT -- JSON WEB TOKEN,网上关于它的介绍已经很多很多啦,在此,推荐给大家一篇写的比较好的文章:什么是 JWT -- JSON WEB TOKEN   以及Token的组成部分:Token存放的信息 OK,今天我想介绍的不再是理论,而是如何在C#中应用,说白了就是怎么写程序呗。
8395 0
|
6月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
189 3
|
6月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
196 3
|
7天前
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
19 3
|
28天前
|
安全 C# 数据安全/隐私保护
实现C#编程文件夹加锁保护
【10月更文挑战第16天】本文介绍了两种用 C# 实现文件夹保护的方法:一是通过设置文件系统权限,阻止普通用户访问;二是使用加密技术,对文件夹中的文件进行加密,防止未授权访问。提供了示例代码和使用方法,适用于不同安全需求的场景。
|
2月前
|
API C#
C# 一分钟浅谈:文件系统编程
在软件开发中,文件系统操作至关重要。本文将带你快速掌握C#中文件系统编程的基础知识,涵盖基本概念、常见问题及解决方法。文章详细介绍了`System.IO`命名空间下的关键类库,并通过示例代码展示了路径处理、异常处理、并发访问等技巧,还提供了异步API和流压缩等高级技巧,帮助你写出更健壮的代码。
39 2
|
2月前
|
安全 程序员 编译器
C#一分钟浅谈:泛型编程基础
在现代软件开发中,泛型编程是一项关键技能,它使开发者能够编写类型安全且可重用的代码。C# 自 2.0 版本起支持泛型编程,本文将从基础概念入手,逐步深入探讨 C# 中的泛型,并通过具体实例帮助理解常见问题及其解决方法。泛型通过类型参数替代具体类型,提高了代码复用性和类型安全性,减少了运行时性能开销。文章详细介绍了如何定义泛型类和方法,并讨论了常见的易错点及解决方案,帮助读者更好地掌握这一技术。
71 11