c# 谷歌动态口令对接
https://www.cnblogs.com/easyauthor/p/11054869.html
Google 身份验证器与两步验证功能配合,可在您登录 Google 帐户时为您平添一重安全保障。
启用两步验证之后,当您登录帐户时,需要提供密码和此应用生成的验证码。配置完成后,无需网络连接或蜂窝连接即可获得验证码。
功能包括:
- 通过 QR 码自动设置
- 支持多帐户登录
- 支持基于时间和基于计数器生成验证码
要使用 Google 身份验证器,需要先为您的 Google 帐户启用两步验证。访问 http://www.google.com/2step 即可立即启用。
demo:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace GoogleAuthenticator
{
class Program
{
static void Main(string[] args)
{
long duration = ;
string key = "xeon997@foxmail.com";
GoogleAuthenticator authenticator = new GoogleAuthenticator(duration, key);
var mobileKey = authenticator.GetMobilePhoneKey(); while (true)
{ Console.WriteLine("手机端秘钥为:" + mobileKey); var code = authenticator.GenerateCode();
Console.WriteLine("动态验证码为:" + code); Console.WriteLine("刷新倒计时:" + authenticator.EXPIRE_SECONDS); System.Threading.Thread.Sleep();
Console.Clear();
}
}
}
}
认证器:
using GoogleAuthorization;
using System;
using System.Security.Cryptography;
using System.Text;
namespace GoogleAuthenticator
{
public class GoogleAuthenticator
{
/// <summary>
/// 初始化验证码生成规则
/// </summary>
/// <param name="key">秘钥(手机使用Base32码)</param>
/// <param name="duration">验证码间隔多久刷新一次(默认30秒和google同步)</param>
public GoogleAuthenticator(long duration = , string key = "xeon997@foxmail.com")
{
this.SERECT_KEY = key;
this.SERECT_KEY_MOBILE = Base32.ToString(Encoding.UTF8.GetBytes(key));
this.DURATION_TIME = duration;
} /// <summary>
/// 间隔时间
/// </summary>
private long DURATION_TIME { get; set; } /// <summary>
/// 迭代次数
/// </summary>
private long COUNTER
{
get
{
return (long)(DateTime.UtcNow - new DateTime(, , , , , , DateTimeKind.Utc)).TotalSeconds / DURATION_TIME;
}
} /// <summary>
/// 秘钥
/// </summary>
private string SERECT_KEY { get; set; } /// <summary>
/// 手机端输入的秘钥
/// </summary>
private string SERECT_KEY_MOBILE { get; set; } /// <summary>
/// 到期秒数
/// </summary>
public long EXPIRE_SECONDS
{
get
{
return (DURATION_TIME - (long)(DateTime.UtcNow - new DateTime(, , , , , , DateTimeKind.Utc)).TotalSeconds % DURATION_TIME);
}
} /// <summary>
/// 获取手机端秘钥
/// </summary>
/// <returns></returns>
public string GetMobilePhoneKey()
{
if (SERECT_KEY_MOBILE == null)
throw new ArgumentNullException("SERECT_KEY_MOBILE");
return SERECT_KEY_MOBILE;
} /// <summary>
/// 生成认证码
/// </summary>
/// <returns>返回验证码</returns>
public string GenerateCode()
{
return GenerateHashedCode(SERECT_KEY, COUNTER);
} /// <summary>
/// 按照次数生成哈希编码
/// </summary>
/// <param name="secret">秘钥</param>
/// <param name="iterationNumber">迭代次数</param>
/// <param name="digits">生成位数</param>
/// <returns>返回验证码</returns>
private string GenerateHashedCode(string secret, long iterationNumber, int digits = )
{
byte[] counter = BitConverter.GetBytes(iterationNumber); if (BitConverter.IsLittleEndian)
Array.Reverse(counter); byte[] key = Encoding.ASCII.GetBytes(secret); HMACSHA1 hmac = new HMACSHA1(key, true); byte[] hash = hmac.ComputeHash(counter); int offset = hash[hash.Length - ] & 0xf; int binary =
((hash[offset] & 0x7f) << )
| ((hash[offset + ] & 0xff) << )
| ((hash[offset + ] & 0xff) << )
| (hash[offset + ] & 0xff); int password = binary % (int)Math.Pow(, digits); // 6 digits return password.ToString(new string('', digits));
}
}
}
using System;
namespace GoogleAuthorization
{
public static class Base32
{
public static byte[] ToBytes(string input)
{
if (string.IsNullOrEmpty(input))
{
throw new ArgumentNullException("input");
} input = input.TrimEnd('=');
int byteCount = input.Length * / ;
byte[] returnArray = new byte[byteCount]; byte curByte = , bitsRemaining = ;
int mask = , arrayIndex = ; foreach (char c in input)
{
int cValue = CharToValue(c); if (bitsRemaining > )
{
mask = cValue << (bitsRemaining - );
curByte = (byte)(curByte | mask);
bitsRemaining -= ;
}
else
{
mask = cValue >> ( - bitsRemaining);
curByte = (byte)(curByte | mask);
returnArray[arrayIndex++] = curByte;
curByte = (byte)(cValue << ( + bitsRemaining));
bitsRemaining += ;
}
} if (arrayIndex != byteCount)
{
returnArray[arrayIndex] = curByte;
} return returnArray;
} public static string ToString(byte[] input)
{
if (input == null || input.Length == )
{
throw new ArgumentNullException("input");
} int charCount = (int)Math.Ceiling(input.Length / 5d) * ;
char[] returnArray = new char[charCount]; byte nextChar = , bitsRemaining = ;
int arrayIndex = ; foreach (byte b in input)
{
nextChar = (byte)(nextChar | (b >> ( - bitsRemaining)));
returnArray[arrayIndex++] = ValueToChar(nextChar); if (bitsRemaining < )
{
nextChar = (byte)((b >> ( - bitsRemaining)) & );
returnArray[arrayIndex++] = ValueToChar(nextChar);
bitsRemaining += ;
} bitsRemaining -= ;
nextChar = (byte)((b << bitsRemaining) & );
} if (arrayIndex != charCount)
{
returnArray[arrayIndex++] = ValueToChar(nextChar);
while (arrayIndex != charCount) returnArray[arrayIndex++] = '=';
} return new string(returnArray);
} private static int CharToValue(char c)
{
var value = (int)c; if (value < && value > )
{
return value - ;
}
if (value < && value > )
{
return value - ;
}
if (value < && value > )
{
return value - ;
} throw new ArgumentException("Character is not a Base32 character.", "c");
} private static char ValueToChar(byte b)
{
if (b < )
{
return (char)(b + );
} if (b < )
{
return (char)(b + );
} throw new ArgumentException("Byte is not a value Base32 value.", "b");
}
}
}
关于二维码的内容:
String format = "otpauth://totp/帐号?secret=密钥";
生成二维码就可以了。 有用的请点赞下 谢谢。
c# 谷歌动态口令对接的更多相关文章
- Google authenticator 谷歌身份验证,实现动态口令
Google authenticator 谷歌身份验证,实现动态口令 google authenticator php 服务端 使用PHP类 require_once '../PHPGangsta/G ...
- php集成动态口令认证
这篇文章主要为大家详细介绍了php集成动态口令认证,动态口令采用一次一密.用过密码作废的方式来提高安全性能,感兴趣的小伙伴们可以参考一下 大多数系统目前均使用的静态密码进行身份认证登录,但由于静态密码 ...
- poptest老李谈动态口令原理
poptest老李谈动态口令原理 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908 ...
- 使用OTP动态口令(每分钟变一次)进行登录认证
GIT地址:https://github.com/suyin58/otp-demo 在对外网开放的后台管理系统中,使用静态口令进行身份验证可能会存在如下问题: (1) 为了便于记忆,用户多选择有特征作 ...
- FreeRadius+GoogleAuthenticator实现linux动态口令认证
简介 在运维管理中,服务器的密码管理十分重要.服务器数量少的时候还好说,可以定时来改密码.一旦数量多了,再来改密码就不现实了. 前提 我们假定运维访问服务器是这样的: 创建一个普通用户用于登录服务器, ...
- [Python学习笔记-003] 使用PyOTP获取基于OTOP算法的动态口令
建立安全的VPN连接,不仅需要输入用户名和密码,还需要输入动态口令(token).作为一个懒人,我更喜欢什么手工输入都不需要,既不需要输入password,也不需要输入token.也就是说,只需一个命 ...
- YS动态口令系统接入流程
动态口令是保护用户账户的一种常见有效手段,即用户进行敏感操作(比如登录)时,需要用户提供此动态生成的口令做二次身份验证,假设用户的口令被盗,如果没有动态口令,也无法进行登录或进行敏感操作,保护了用户的 ...
- 使用google身份验证器实现动态口令验证
最近有用户反应我们现有的短信+邮件验证,不安全及短信条数限制和邮件收验证码比较慢的问题,希望我们 也能做一个类似银行动态口令的验证方式.经过对可行性的分析及慎重考虑,可以实现一个这样的功能. 怎么实现 ...
- asp.net mvc 使用 Autocomplete 实现类似百度,谷歌动态搜索条提示框。
Autocomplete是一个Jquery的控件,用法比较简单. 大家先看下效果: 当文本框中输入内容,自动检索数据库给出下拉框进行提示功能. 需要用此控件大家先到它的官方网站进行下载最新版本: ht ...
随机推荐
- JS对象—数组总结(创建、属性、方法)
JS对象—数组总结(创建.属性.方法) 1.创建字符串 1.1 new Array() var arr1 = new Array(); var arr2 = new Array(6); 数组的长度为6 ...
- mariadb数据库增删改查
1.常用数据类型 1)整数:int, bit 2)小数:decimal #decimal(5,2)表示共有五位数,保留两位小数 3)字符串:varchar, char 4)日期时间:date, ...
- python 并发编程 异步IO模型
异步IO(Asynchronous I/O) Linux下的asynchronous IO其实用得不多,从内核2.6版本才开始引入.先看一下它的流程: 用户进程发起read操作之后,立刻就可以开始去做 ...
- mysql for update 高并发 死锁研究
mysql for update语句 https://www.cnblogs.com/jtlgb/p/8359266.html For update带来的思考 http://www.cnblo ...
- linux操作系统安装运行Redis
Redis是c语言开发的. 安装redis需要c语言的编译环境.如果没有gcc需要在线安装.yum install gcc-c++ 安装步骤: 1.安装gcc yum install gcc ...
- python3.6 使用newspaper库的Article包来快速抓取网页的文章或者新闻等正文
我主要是用了两个方法来抽去正文内容,第一个方法,诸如xpath,css,正则表达式,beautifulsoup来解析新闻页面的时候,总是会遇到这样那样各种奇奇怪怪的问题,让人很头疼.第二个方法是后面标 ...
- wordpress后台编辑如何显示定义的`style.css`样式
wordpress后台编辑如何显示定义的style.css样式 由于公司官网采用wordpress进行搭建,但是却又自己设计页面,无奈主题只能自行构建了,直接修改wordpress自带的主题进行修改. ...
- [JavaScript] es6规则总结
let 和 const let 是块级作用域 let 声明的变量只在其所在的作用域内生效 <script> { var today = "周3"; let yester ...
- php转码 iconv和mb_convert_encoding
最近在给公司做一个小工具,将excel表格按照一定的格式转为txt文本格式,要求转后的txt文本是GBK编码,但是总会有几个excel表格无法正常转码,最后查阅相关资料,得到解决方案 先说明下,在ph ...
- 外壳程序(shell):命令解释器commond
在Linux系统中有好几种shell,常见的有:ash.bash.zsh.ksh.tcsh等,计算机一般默认的是bash,使用命令echo $SHELL可以看出我们使用的哪种shell