Google动态验证码

Google动态验证码作用:可以动态的生成一个6位数的验证码,可以用于双重验证,增加网站的安全性。

条件:首先需要在手机上下载一个Google 验证器。(google authenticator app)

还需要在你的项目中引入一个Jar最主要的

<dependency>    <groupId>commons-codec</groupId>    <artifactId>commons-codec</artifactId>    <version>1.13</version></dependency>

一个主要的方法
import org.apache.commons.codec.binary.Base32;import org.apache.commons.codec.binary.Base64;

import javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;

public class GoogleAuthenticatorUtil {    // 生成的key长度( Generate secret key length)    public static final int SECRET_SIZE = 10;

    public static final String SEED = "g8GjEvTbW5oVSV7avL47357438reyhreyuryetredLDVKs2m0QN7vxRs2im5MDaNCWGmcD2rvcZx";    // Java实现随机数算法    public static final String RANDOM_NUMBER_ALGORITHM = "SHA1PRNG";    // 最多可偏移的时间    int window_size = 3; // default 3 - max 17

    /**     * set the windows size. This is an integer value representing the number of     * 30 second windows we allow The bigger the window, the more tolerant of     * clock skew we are.     *     * @param s     *            window size - must be >=1 and <=17. Other values are ignored     */    public void setWindowSize(int s) {        if (s >= 1 && s <= 17)            window_size = s;    }

    /**     * Generate a random secret key. This must be saved by the server and     * associated with the users account to verify the code displayed by Google     * Authenticator. The user must register this secret on their device.     * 生成一个随机秘钥     *     * @return secret key     */    public static String generateSecretKey() {        SecureRandom sr = null;        try {            sr = SecureRandom.getInstance(RANDOM_NUMBER_ALGORITHM);            sr.setSeed(Base64.decodeBase64(SEED));            byte[] buffer = sr.generateSeed(SECRET_SIZE);            Base32 codec = new Base32();            byte[] bEncodedKey = codec.encode(buffer);            String encodedKey = new String(bEncodedKey);            return encodedKey;        } catch (NoSuchAlgorithmException e) {            // should never occur... configuration error        }        return null;    }

    /**     * Return a URL that generates and displays a QR barcode. The user scans     * this bar code with the Google Authenticator application on their     * smartphone to register the auth code. They can also manually enter the     * secret if desired     *     * @param user     *            user id (e.g. fflinstone)     * @param host     *            host or system that the code is for (e.g. myapp.com)     * @param secret     *            the secret that was previously generated for this user     * @return the URL for the QR code to scan     */    public static String getQRBarcodeURL(String user, String host, String secret) {        String format = "http://www.google.com/chart?chs=200x200&chld=M%%7C0&cht=qr&chl=otpauth://totp/%[email protected]%s?secret=%s";        return String.format(format, user, host, secret);    }

    /**     * 生成一个google身份验证器,识别的字符串,只需要把该方法返回值生成二维码扫描就可以了。     *     * @param user     *            账号     * @param secret     *            密钥     * @return     */    public static String getQRBarcode(String user, String secret) {        String format = "otpauth://totp/%s?secret=%s";        return String.format(format, user, secret);    }

    /**     * Check the code entered by the user to see if it is valid 验证code是否合法     *     * @param secret     *            The users secret.     * @param code     *            The code displayed on the users device     * @param timeMsec     *            The time in msec (System.currentTimeMillis() for example)     * @return     */    public boolean check_code(String secret, String code, long timeMsec) {        Base32 codec = new Base32();        byte[] decodedKey = codec.decode(secret);        // convert unix msec time into a 30 second "window"        // this is per the TOTP spec (see the RFC for details)        long t = (timeMsec / 1000L) / 30L;        // Window is used to check codes generated in the near past.        // You can use this value to tune how far you‘re willing to go.        for (int i = -window_size; i <= window_size; ++i) {            long hash;            try {                hash = verify_code(decodedKey, t + i);            } catch (Exception e) {                // Yes, this is bad form - but                // the exceptions thrown would be rare and a static                // configuration problem                e.printStackTrace();                throw new RuntimeException(e.getMessage());                // return false;            }            if (String.format ( "%06d",hash ).equals(code)) {                return true;            }        }        // The validation code is invalid.        return false;    }

    private static int verify_code(byte[] key, long t) throws NoSuchAlgorithmException, InvalidKeyException {        byte[] data = new byte[8];        long value = t;        for (int i = 8; i-- > 0; value >>>= 8) {            data[i] = (byte) value;        }        SecretKeySpec signKey = new SecretKeySpec(key, "HmacSHA1");        Mac mac = Mac.getInstance("HmacSHA1");        mac.init(signKey);        byte[] hash = mac.doFinal(data);        int offset = hash[20 - 1] & 0xF;        // We‘re using a long because Java hasn‘t got unsigned int.        long truncatedHash = 0;        for (int i = 0; i < 4; ++i) {            truncatedHash <<= 8;            // We are dealing with signed bytes:            // we just keep the first byte.            truncatedHash |= (hash[offset + i] & 0xFF);        }        truncatedHash &= 0x7FFFFFFF;        truncatedHash %= 1000000;        return (int) truncatedHash;    }}

做一下测试
 private static String secret = "MRHMHLZPFBZEZWQ3";

    @Test    public void getSecret(){//首先跑这个类,成功后得到的secret要赋给上面的secret        secret = GoogleAuthenticatorUtil.generateSecretKey();//        String qrCode = GoogleAuthenticatorUtil.getQRBarcodeURL("haha","http://10.10.10.124:8092",secret);        String qrCode = GoogleAuthenticatorUtil.getQRBarcode("haha",secret);        System.out.println("secret "+secret + " qrCode " + qrCode );//qrcode这个我们可以最为二维码的值,我这个是在前端用qrcode.min.js生成的一个二维码(需要用户扫码用的),将值加进去就可以了。    }    @Test    public void testValidCode(){        String code = "105799";//这个值是你再Google APP中拿到的动态验证码        long time = System.currentTimeMillis ();        GoogleAuthenticatorUtil g = new GoogleAuthenticatorUtil();        System.out.println("secret "+secret );        boolean result = g.check_code (secret,code,time);        System.out.println ( result );//true就是表示验证码成功,否则失败    }

同时生成的二维码,我们除了用前端的qrcode.min.js我们还可以用java生成一个二维码图片显示在页面上需要一些google的jar包
import com.google.zxing.BarcodeFormat;import com.google.zxing.EncodeHintType;import com.google.zxing.client.j2se.MatrixToImageWriter;import com.google.zxing.common.BitMatrix;import com.google.zxing.qrcode.QRCodeWriter;import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import java.awt.image.BufferedImage;import java.io.IOException;import java.util.HashMap;/**width:宽,height:高。content就是我们也要设置的二维码的值,google验证器的格式是
"otpauth://totp/" + user+ "?secret=" + secret;
public class QRCodeUtil {

    public static void createQRCode(HttpServletResponse response, String content, int width, int height) throws IOException {        if (!StringUtil.isNullOrEmpty(content)) {            response.setDateHeader("Expires", 0);            // Set standard HTTP/1.1 no-cache headers.            response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");            // Set IE extended HTTP/1.1 no-cache headers (use addHeader).            response.addHeader("Cache-Control", "post-check=0, pre-check=0");            // Set standard HTTP/1.0 no-cache header.            response.setHeader("Pragma", "no-cache");            // return a jpeg            response.setContentType("image/png");            ServletOutputStream out = response.getOutputStream();            try {                HashMap<EncodeHintType, Comparable> hints = new HashMap<>(3);                hints.put(EncodeHintType.CHARACTER_SET, "utf-8");                hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);                hints.put(EncodeHintType.MARGIN, 2);

                QRCodeWriter writer = new QRCodeWriter();                BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);

                BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);                ImageIO.write(bufferedImage, "png", out);            } catch (Exception e) {                e.printStackTrace();            } finally {                if (out != null) {                    out.flush();                    out.close();                }            }        }    }}我们除了自己写类,也可以引入google验证器的jar
<dependency>    <groupId>com.warrenstrange</groupId>    <artifactId>googleauth</artifactId>    <version>1.2.0</version></dependency>
GoogleAuthenticator gAuth = new GoogleAuthenticator();
String secret= gAuth.createCredentials().getKey();//得到secret
gAuth.authorize(key, code)//验证

原文地址:https://www.cnblogs.com/echo777/p/11758824.html

时间: 2024-10-31 09:08:33

Google动态验证码的相关文章

Linux使用ssh动态验证码登录机器

ssh动态验证码登录机器 Google Authenticator是一个动态验证码程序,兼容各种智能手机平板设备,可以用来做各种帐号的二次验证,增加帐号的安全性.SSH是Linux系统的最重要防线之一,为了防止密码泄露或者被爆破,可以使用Google Authenticator来做二次验证,使用方法也很简单 谷歌身份验证器生成的是动态验证码,默认30秒更新.修改配置,SSH登录必须在输入密码之前输入动态验证码.即使账号和密码泄露,验证码输入错误,仍然无法登录.苹果或者安卓手机端可以安装身份验证器

Servlet动态验证码的生成-带数字和字母

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 一.实现的思路: (1)首先,需要创建一个Servlet.该Servlet通过字节型响应给客户端返回一个图片,该图片是通过JDK中Java 2D的类库来生成一个图片.图片的生成是依靠一个随机数来完成,然后将这个随机数写成图片格式.最后在Session将这个随机的字符串的状态保持住,以便在用户填写后进行对比. (2)其次,在需要加入验证码的JSP页面中,通过<img src="生成验证码

登录页面动态验证码的设置

登录页面动态验证码的设置 采用php中创建对象的思想进行动态验证码的设置 1.创建出一个背景图片,用来存放动态码输出位置 1 function createImage(){ 2 // 创建图片对象,并设置图片的宽高 imagecreatetruecolor 3 $this->image = imagecreatetruecolor($this->width, $this->height); 4 // 图片创建背景颜色 5 // rand(下界,上界), php中的随机数 6 $backg

【Web】Java生成中文GIF动态验证码-集成SpringMVC

转载请注明出处:http://blog.csdn.net/qq_26525215 本文源自[大学之旅_谙忆的博客] 说明 GIF验证码相对于JPG图片验证码来说,要更难破解一些,加大了破解的代价. 从昨天到现在,写了一个小小的GIF验证码项目(中文成语). 当然,你可以自己修改成字母数字的.我只是单纯的觉得中文验证码的破解代价更高一点~ 我在这里生成GIF图片的类,用到了国外牛人的三个类,也就是: AnimatedGifEncoder LZWEncoder 和NeuQuant,这三个类. 没办法

12306的动态验证码变成静态

本以为这次12306的动态验证码很厉害,什么刷票软件都不行了,看了以后发现并不是很复杂,估计不出两日刷票软件又会卷土重来,开来要一个验证码很难遏制这些刷票软了. 这次换的动态验证码采用的是GIF格式在客户端输出,至于要拿到这个gif文件然后把动态图的各张图片拼凑起来就能得到完整的静态验证码,接下来就是识别静态验证码的事情了. 比如这张动态验证码 他的静态效果就是 下面是随手写的代码,有点混乱 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2

C# 获取动态验证码?

如何获取动态验证码(比如登录验证码,每次访问码值都是不一样的).本来想从cookie上入手但是,每次访问虽然码值不一样,但是后来发现它们的cookie一样的.这个道路就行不通了.目前知道一个解决方案,就是通过WebBrowser获取然后显示的html,1.种方法直接截图:2.将图片元素的DomElement作为参数,方法如下.但是这种方法效率太低..,求高效的方法.结合mshtml.dll. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [ComI

Servlet仿CSDN动态验证码的生成-带数字和字母

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 一.实现的思路: (1)首先,须要创建一个Servlet.该Servlet通过字节型响应给client返回一个图片.该图片是通过JDK中Java 2D的类库来生成一个图片. 图片的生成是依靠一个随机数来完毕,然后将这个随机数写成图片格式.最后在Session将这个随机的字符串的状态保持住,以便在用户填写后进行对照. (2)其次,在须要加入验证码的JSP页面中,通过<img src="生

ASP.Net一般处理程序生成动态验证码

using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Web; namespace 动态验证码生成 { /// <summary> /// Handler1 的摘要说明 /// </summary> public class Handler1 : IHttpHandler {

iOS本地动态验证码生成-b

用于ios本地动态生成验证码,效果如下: demo.gif 导入CoreGraphics.framework用于绘制图形 封装UIView,便捷使用,代码如下: AuthcodeView.h #import <UIKit/UIKit.h> @interface AuthcodeView : UIView @property (strong, nonatomic) NSArray *dataArray;//字符素材数组 @property (strong, nonatomic) NSMutabl