博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何开发两步验证功能
阅读量:4448 次
发布时间:2019-06-07

本文共 2912 字,大约阅读时间需要 9 分钟。

什么是两步验证

  两步验证,是指用户登录账户的时候,除了要输入用户名和密码,还要求用户输入一个动态密码,为帐户添加了一层额外保护。这个动态密码要么是专门的硬件,要么由用户手机APP提供。即使入侵者窃取了用户密码,也会因不能使用用户手机而无法登录帐户。许多游戏客户端和网银采用这种方式。以银行为例,当用户进行转账操作时,第一步输入6位取款密码,第二步输入动态密码器上数字,这个密码器是开户时银行提供的硬件。

fc0617ba6b2062bec68c87eb481d25c1_hd.jpg

动态密码原理

  客户端和服务器事先协商好一个密钥K,用于一次性密码的生成过程,此密钥不被任何第三方所知道。此外,客户端和服务器各有一个计数器C,并且事先将计数值同步。进行验证时,客户端对密钥和计数器的组合(K,C)使用HMAC(Hash-based Message Authentication Code)算法计算一次性密码,公式如下:HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))上面采用了HMAC-SHA-1,当然也可以使用HMAC-MD5等。HMAC算法得出的值位数比较多,不方便用户输入,因此需要截断(Truncate)成为一组不太长十进制数(例如6位)。计算完成之后客户端计数器C计数值加1。用户将这一组十进制数输入并且提交之后,服务器端同样的计算,并且与用户提交的数值比较,如果相同,则验证通过,服务器端将计数值C增加1。如果不相同,则验证失败。

业务流程

  如何开发这个功能呢?我们先理清它的流程:

  1. 第一步:输入常规帐号密码,验证成功后进入二次验证页面。
  2. 第二步:二次验证页面要求用户输入动态密码,用户手机必须先通过APP绑定帐号后才能获取动态密码,APP推荐。
  3. 第三步:页面生成二维码,内容是URI地址otpauth://totp/账号?secret=密钥,用eagle2fa扫码后绑定帐号,把密钥保存在客户端,如下图所示:
    o_eagle2fa.png
  4. 第四步:输入APP上的6位数字,验证通过进入用户中心页面。
    最重要的功能是生成二维码验证动态密码

组件选型

googleauth是Google Authenticator的开源实现

com.warrenstrange
googleauth
1.1.2

zxing用于生成二维码图片

com.google.zxing
javase
3.3.3

也可以使用其他网站提供的的WEB API,譬如:

http://qr.liantu.com/api.php?text=xx必须用UTF8编码格式,x内容出现&符号时用%26代替,换行符使用%0A

关键代码

以下代码演示怎么使用GoogleAuthenticator包:

private static final GoogleAuthenticator googleAuthenticator = new GoogleAuthenticator();    /**     * 由于只是演示,dao没有操作数据库,真实的场景必然要持久化     */    @Autowired    private UserDao userDao;    @PostConstruct    public void init() {        googleAuthenticator.setCredentialRepository(new ICredentialRepository() {            @Override            public String getSecretKey(String userName) {                //根据帐号查询secretKey                return userDao.getSecretKey(userName);            }            @Override            public void saveUserCredentials(String userName, String secretKey, int validationCode, List
scratchCodes) { //secretKey要保存在数据库中 userDao.saveUserCredentials(userName, secretKey); } }); log.info("GoogleAuthenticator初始化成功"); }

以下代码是生成二维码,uri的格式不能写错。

// 必须按照这个格式,APP才能正常绑定    private static final String KEY_FORMAT = "otpauth://totp/%s?secret=%s";    /**     * 生成二维码链接     */    private String getQrUrl(String username) {        //每次调用createCredentials都会生成新的secretKey        GoogleAuthenticatorKey key = googleAuthenticator.createCredentials(username);        log.info("username={},secretKey={}", username, key.getKey());        return String.format(KEY_FORMAT, username, key.getKey());    }

以下是二次验证方法:

// 验证动态密码  username 帐号, code  app上的6位数字    public boolean validCode(String username, int code) {        return googleAuthenticator.authorizeUser(username, code);    }

参考(部分摘抄的文字版权属于原作者)

https://blog.seetee.me/post/2011/google-two-step-verification/

https://www.zhihu.com/question/20462696/answer/19670601

转载于:https://www.cnblogs.com/xiaoyangjia/p/11512453.html

你可能感兴趣的文章
iOS正确的自定义View方式
查看>>
nginx修改php.ini生效:php-fpm重启与nginx加载配置文件
查看>>
ubuntu下基于sqlite3后台的php环境的搭建
查看>>
Qt 静态库与共享库(动态库)共享配置的一个小办法
查看>>
linux_cacti 配置之 安装snmp 服务
查看>>
201407-至今
查看>>
c# 应用事务
查看>>
优化杭州某著名电子商务网站高并发千万级大型数据库经验之- SQL语句优化(转)...
查看>>
字符串的全排列
查看>>
DtCms.Model.Article.cs
查看>>
chapter02 svm对手写体数字的数码图像进行识别
查看>>
python编码问题 decode与encode
查看>>
hihocoder 1582 : Territorial Dispute (计算几何)(2017 北京网络赛E)
查看>>
files list file for package 'xxx' is missing final newline
查看>>
大数据——zookeeper分布式集群管理工具的学习与使用
查看>>
学习JAVA所需的东西
查看>>
dom4j api 详解--XPath 节点详解
查看>>
java正则表达式基础知识(转)
查看>>
使用babel
查看>>
怎么画流程图(转)
查看>>