美文网首页
大继的基础级业务实战设计记录(四),谷歌令牌

大继的基础级业务实战设计记录(四),谷歌令牌

作者: 大继 | 来源:发表于2018-07-21 14:31 被阅读0次

场景描述

  • 为提高系统安全,多数情况我们使用手机验证码,但是如果操作频率太高,手机验证码经常会丢失,发送太频繁,太多引起验证码丢失问题。所以选用google token来满足。
  • 场景一,后台对积分管理
  • 场景二,订单支付操作等...

满足

  • 用户锁定google令牌
  • 可以用google令牌验证,敏感类型操作。
  • 现非聚群系统也可以使用
  • 多服务聚合使用(保证多个服务集合使用是uri不冲突)
  • 默认原则,能默认就不用定义
  • 资源化restful
  • 防止暴力破解

主要实现

  1. 发行一个用户密钥
  2. 通过旧密钥更新密钥 http://google/authenticates GoogleAuthenticateUserRefreshRequest
  3. 用户向 http://google/authenticates GoogleAuthenticateUserRequest 验证动态码是否正确
  4. 强行更新密钥 PUT http://google/authenticates/xxx GoogleAuthenticate (用于后台管理,或通过手机验证码等更高权重的验证进行刷新或修改)

范围

一个用户只能绑定一个证明 authenticate.

restful设计

TOTP 实现

发行

public GoogleAuthenticate release(Long userId, String account) {

        if(googleAuthenticateRepository.findByUserId(userId) == null){
            GoogleAuthenticate googleAuthenticate = new GoogleAuthenticate();

            googleAuthenticate.setId(UUID.randomUUID().toString());
            googleAuthenticate.setCreateTime(new Date());
            googleAuthenticate.setEnable(true);
            googleAuthenticate.setIssuer(ISSUER);
            googleAuthenticate.setAccount(account);
            googleAuthenticate.setKey(randomSecretKey());
            googleAuthenticate.setUserId(userId);
            googleAuthenticateRepository.save(googleAuthenticate);

            return googleAuthenticate;
        }else {
            throw new RuntimeException("User had already released authenticate.");
        }
    }

验证

public Boolean validate(Long userId, String code) {
        Boolean isAuthenticate = false;

        //连续错误次数  6/1 (次/天) 锁定用户
        GoogleAuthenticateWrongDaliyLog googleAuthenticateWrongDaliyLog =
                googleAuthenticateWrongDailyLogRepository.findByUserIdAndDay(userId,
                        new java.sql.Date(System.currentTimeMillis()));
        if(googleAuthenticateWrongDaliyLog != null &&  googleAuthenticateWrongDaliyLog.getWrongTimes() > 6){
            return false;
        }

        GoogleAuthenticate googleAuthenticate = googleAuthenticateRepository.findByUserId(userId);
        if(googleAuthenticate != null){
            //check
            if(code.equals(getTOTPCode(googleAuthenticate.getKey()))){
                isAuthenticate = true;
            }

        }

        if(!isAuthenticate){
            if(googleAuthenticateWrongDaliyLog == null){
                googleAuthenticateWrongDaliyLog = new GoogleAuthenticateWrongDaliyLog();
                googleAuthenticateWrongDaliyLog.setDay(new java.sql.Date(System.currentTimeMillis()));
                googleAuthenticateWrongDaliyLog.setUserId(userId);
                googleAuthenticateWrongDaliyLog.setWrongTimes(0);
            }
            googleAuthenticateWrongDaliyLog.setWrongTimes(googleAuthenticateWrongDaliyLog.getWrongTimes() + 1);
            googleAuthenticateWrongDailyLogRepository.save(googleAuthenticateWrongDaliyLog);
        }

        return isAuthenticate;
    }

实体设计

@Entity
@Table(name = "google_authenticate",
        indexes = {@Index(columnList = "userId",unique = true)})
public class GoogleAuthenticate {

    @Id
    @Column(length = 37)
    private String id;

    @Column
    private String account;

    @Column(length = 64)
    private String key;

    @Column
    private String issuer;

    @Column
    private Long userId;

    /**
     * 用于锁定用户,如果过于频繁,验证失败。
     */
    @Column
    private Boolean enable;

    @Column
    private Date updateTime;

    @Column
    private Date createTime;
}

验证

@Test
    public void releaseTest(){
        GoogleAuthenticate googleAuthenticate = googleAuthenticateService.release(0L,"daji@qq.com");

        //把输出放,草料生成二维码,导入到 google authenticator
        System.out.println(googleAuthenticateService.produceQrCode(googleAuthenticate));
    }

输出

otpauth://totp/hitstone.cn%3Adaji%40qq.com?secret=3HOKVR3YIM3YXCCOB3WSU34COBFA5MBH&issuer=hitstone.cn
//导入到 google authenticator
image.png
@Test
    public void checkCodeTest(){
        String code = "047345"; //查看google authenticator 填入,并认证。

        System.out.println(googleAuthenticateService.validate(0L,code));
    }

输出

true

由于写的比较冲忙,只对思路进行描述。

参考

相关文章

网友评论

      本文标题:大继的基础级业务实战设计记录(四),谷歌令牌

      本文链接:https://www.haomeiwen.com/subject/mwvopftx.html