扫码登录原理及实践

 

前言

近期实现了一个扫码登录的需求,在此之前没有这方面的开发经历,所以接到这个需求的时候还是有点慌的,最终通过查阅网上的资料以及老大的指导下实现了这个功能,目前已经投入使用,实现之后还是蛮兴奋的。特此记录一下实现的过程。

主要原理

怎么实现的呢?首先得了解其中的原理,由于我只提供后台接口,因此只记录后台接口的来龙去脉。先贴张图吧

图是我自己画的,主要原理其实不难,分为如下几个步骤:

1、前端生成一张二维码,使用qrCode.js插件。

2、前端定时请求后台二维码状态,此时在第一次请求的时候可以记录下时间,作为二维码失效时间的对比,数据存储建议使用redis。

3、手机扫描二维码,此时要请求后台接口,将识别出来的二维码值以及登录信息传入后台,改变后台二维码的状态为【已扫描】。

4、服务器给前端返回【已扫描】标识。

5、手机扫描之后出现确认登录按钮,点击确认登录,请求后台,改变二维码的状态为【已确认】。

6、服务器判断二维码状态为【已确认】之后,便根据用户的登录信息返回用户信息,前端渲染个人主页,实现扫码登录。

实现细节

1、定义一个CodeBean实体类


   
   
  1. public class CodeBean implements Serializable{
  2. // 二维码唯一标识
  3. private String qrCodeValue;
  4. // 二维码状态
  5. private Integer qrCodeStatus;
  6. // 用户登录身份证
  7. private String token;
  8. // 二维码生成时间
  9. private Long createTime;
  10. // 员工工号
  11. private String workerNo;
  12. public String getWorkerNo() {
  13. return workerNo;
  14. }
  15. public void setWorkerNo(String workerNo) {
  16. this.workerNo = workerNo;
  17. }
  18. public Long getCreateTime() {
  19. return createTime;
  20. }
  21. public void setCreateTime(Long createTime) {
  22. this.createTime = createTime;
  23. }
  24. public String getQrCodeValue() {
  25. return qrCodeValue;
  26. }
  27. public void setQrCodeValue(String qrCodeValue) {
  28. this.qrCodeValue = qrCodeValue;
  29. }
  30. public Integer getQrCodeStatus() {
  31. return qrCodeStatus;
  32. }
  33. public void setQrCodeStatus(Integer qrCodeStatus) {
  34. this.qrCodeStatus = qrCodeStatus;
  35. }
  36. public String getToken() {
  37. return token;
  38. }
  39. public void setToken(String token) {
  40. this.token = token;
  41. }
  42. }

 

2、提供给app端的接口


   
   
  1. public RstUtil loginByCode(CommonRemoteInputBean bean, AppMainBean mainBean) {
  2. // 参数判断,此处省略
  3. JSONObject json = new JSONObject();
  4. long endTime = 0;
  5. long startTime = 0;
  6. String qRCodeValue = bean.getQrCodeValue();
  7. String appName = bean.getAppName();
  8. // app扫码
  9. if (bean.getLoginStep() == 1) {
  10. endTime = System.currentTimeMillis();
  11. // 判断是否失效
  12. CodeBean codeBean = MobileRedisUtil.getCode(qRCodeValue);
  13. if (codeBean != && codeBean.getCreateTime() != ) {
  14. startTime = codeBean.getCreateTime();
  15. }
  16. if (endTime - startTime >= SystemParamConstant.QRCODE_EXPIRETIME) {
  17. // 二维码失效
  18. MobileRedisUtil.removeCode(qRCodeValue);
  19. return RstUtil.getRstUtil( false, RstUtil.ERROR, "二维码失效");
  20. }
  21. LoginUserBean userBean = MobileRedisUtil.getLoginUser(mainBean.getEmpNumber(), appName, bean.getToken());
  22. if ( != userBean && bean.getToken().equals(userBean.getToken())) {
  23. codeBean.setToken(bean.getToken());
  24. // 设置二维码状态为已扫描
  25. codeBean.setQrCodeStatus(SystemParamConstant.QRCODE_SCANNED);
  26. codeBean.setWorkerNo(mainBean.getEmpNo());
  27. MobileRedisUtil.saveCode(codeBean);
  28. json.put( "data", codeBean);
  29. return RstUtil.getRstUtil( true, RstUtil.SUCCESS, "扫描成功!", json);
  30. } else {
  31. MobileRedisUtil.removeCode(qRCodeValue);
  32. return RstUtil.getRstUtil( false, RstUtil.ERROR, "未获取到人员信息!");
  33. }
  34. }
  35. // 2、app确认登录
  36. if(bean.getLoginStep() == 2) {
  37. LoginUserBean userBean = MobileRedisUtil.getLoginUser(mainBean.getEmpNumber(),appName, bean.getToken());
  38. CodeBean codeBean = MobileRedisUtil.getCode(qRCodeValue);
  39. if ( != userBean && bean.getToken().equals(userBean.getToken())) {
  40. if (codeBean != &&
  41. SystemParamConstant.QRCODE_SCANNED.equals(codeBean.getQrCodeStatus())){
  42. codeBean.setQrCodeStatus(SystemParamConstant.QRCODE_CONFIRMED);
  43. json.put( "data", codeBean);
  44. MobileRedisUtil.saveCode(codeBean);
  45. }
  46. }
  47. return RstUtil.getRstUtil( true, RstUtil.SUCCESS, , json);
  48. }
  49. return RstUtil.getRstUtil( false, RstUtil.ERROR, "系统异常!");
  50. }

 

3、前端请求的接口


   
   
  1. /**
  2. * 二维码扫码登陆
  3. * @param bean
  4. * @param mainBean
  5. * @return
  6. */
  7. private RstUtil qrCodeLogin(CommonRemoteInputBean bean,AppMainBean mainBean){
  8. if( == MobileRedisUtil.getCode(bean.getQrCodeValue())){
  9. CodeBean codeBean = new CodeBean();
  10. codeBean.setCreateTime(System.currentTimeMillis());
  11. codeBean.setQrCodeValue(bean.getQrCodeValue());
  12. codeBean.setQrCodeStatus(SystemParamConstant.QRCODE_CREATED);
  13. MobileRedisUtil.saveCode(codeBean);
  14. }
  15. // 获取是否存在确认登陆信息
  16. CodeBean codeBean = MobileRedisUtil.getCode(bean.getQrCodeValue());
  17. // 如果用户已经点击确认登陆,直接登陆系统
  18. if(SystemParamConstant.QRCODE_CONFIRMED.equals(codeBean.getQrCodeStatus())){
  19. String appName = bean.getAppName();
  20. if(StringUtil.isEmpty(appName)){
  21. appName = mainBean.getAppName();
  22. }
  23. try {
  24. UserBean user = getLoginUser(codeBean.getWorkerNo() , );
  25. LoginUserBean userBean = MobileRedisUtil.getLoginUser(user.getWorkerId(), "jjr", codeBean.getToken());
  26. // 保存登陆信息
  27. if(userBean != && codeBean.getToken().equals(userBean.getToken())) {
  28. // 生成用户登陆token
  29. user.setToken(userBean.getToken());
  30. userBean.setAppName(appName);
  31. userBean.setLoginTime( new Date());
  32. userBean.setImei(mainBean.getImei());
  33. userBean.setServiceCode(mainBean.getServiceCode());
  34. MobileRedisUtil.saveLoginUser(userBean);
  35. } else {
  36. MobileRedisUtil.removeCode(codeBean.getQrCodeValue());
  37. return RstUtil.getRstUtil( false, RstUtil.ERROR, "登录失败!");
  38. }
  39. // 删除二维码标识
  40. MobileRedisUtil.removeCode(codeBean.getQrCodeValue());
  41. JSONObject json = new JSONObject();
  42. json.put( "data", user);
  43. return RstUtil.getRstUtil( true, RstUtil.SUCCESS, "登录成功!", json);
  44. } catch (Exception e) {
  45. MobileRedisUtil.removeCode(codeBean.getQrCodeValue());
  46. e.printStackTrace();
  47. return RstUtil.getRstUtil( false, RstUtil.ERROR, "登录失败!");
  48. }
  49. }
  50. if(SystemParamConstant.QRCODE_SCANNED.equals(codeBean.getQrCodeStatus())) {
  51. return RstUtil.getRstUtil( true, RstUtil.SUCCESS, "已扫描,请在手机端确认");
  52. }
  53. if(SystemParamConstant.QRCODE_CREATED.equals(codeBean.getQrCodeStatus())) {
  54. return RstUtil.getRstUtil( true, RstUtil.SUCCESS, "");
  55. }
  56. return RstUtil.getRstUtil( false, RstUtil.ERROR, "暂未确认登录!");
  57. }

 

几个值得注意的地方:

1、二维码失效或使用完必须删除在redis中存储的信息。

2、人员验证需要使用token。

整体就是这样,前端的细节此处就不再详述了,有兴趣的同学可以再评论底下留言,相互探讨下也是十分乐意的

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值