基于分布式文件系统 FastDFS,利用 Zuul 网关实现滑块验证登录

news/2024/7/24 8:08:35 标签: java, redis, mysql, spring, 数据库

点击上方蓝色“架构荟萃”关注我们,输入1024,你懂的

需求分析

现在滑块验证码在许多网站逐步流行起来,比如今日头条搜新闻时会提示滑块验证。

一方面,滑块验证对用户体验来说,比较新颖,操作简单。另一方面其安全性相对于图形验证码来说,并没有降低多少。当然没有绝对的安全验证,只是在不断增加攻击者的穿透成本。另外,还可以起到宣传企业愿景和重大历史事件的作用。

最终效果图

关键技术栈

  1. SpringCloud

  2. FastDFS:分布式文件系统

  3. Redis:利用 Go 语言编写的 Codis 作为分布式缓存系统

  4. Mysql

  5. Docker/K8s 容器平台

设计要点

1、如何生成滑块临时大图以及小图

2、前后端分离,脱离传统 Session 会话机制,如何存储用户会话滑块图片参数

3、最佳滑块验证方式:统一入口网关验证

滑动验证流程分析

1、服务端随机生成小图和带有小图阴影的背景大图,服务端保存随机抠图位置坐标;

2、前端实现滑动交互,将小图拼在大图阴影之上,同时获取用户滑动距离值(一般语序误差范围在 3-5 像素);

3、前端将用户滑动距离值传入服务端,服务端校验误差是否在容许范围内;验证OK,返回登录验证码

4、服务网关(Zuul)登录验证:通过客户端传值验证码与 redis 缓存验证码比较匹配,决定是否登录成功

数据库设计

滑块主表

CREATE TABLE `us_slide` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`rdm_len` int(11) NOT NULL DEFAULT '5' COMMENT '随机图片总数',
`img_prefix` varchar(20) DEFAULT 'login_slide_img_' COMMENT '随机图片默认编号前缀:slide_img_',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

滑块-随机图片表-从表

CREATE TABLE `us_slide_image` (
`img_no` varchar(20) NOT NULL COMMENT '图片编号',
`img_url` varchar(200) NOT NULL COMMENT '图片地址',
`sid` bigint(20) NOT NULL COMMENT '滑块外键ID',
`expire` char(1) DEFAULT '1' COMMENT '1是过期',
PRIMARY KEY (`img_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

滑块-临时图片记录表:用于通过 fastdfs 删除历史临时滑块图片

CREATE TABLE `us_slide_image_record` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`his_img_url` varchar(200) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=540 DEFAULT CHARSET=utf8;

分布式文件系统设计:FastDFS

FastDFS

是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等。

Maven 依赖

<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
</dependency>

参数配置

fdfs:
  soTimeout: 30000
  connectTimeout: 20000
  thumbImage:
  width: 150
  height: 150
  trackerList:
    - 127.0.0.1:22122

FastDFSClient 工具类设计 

滑块验证相关接口设计

初始化用户登录大小图片接口设计

/slide/v1/opi/initial-image

RecordRunnar 线程

由于早8点-9点用户登录频次最高,为了提高程序并发请求性能,可以利用 Java 线程池异步多线程方式,异步保存临时图片存储记录,然后用于临时图片清理工具(imgcleaner)单独清理。

java">class RecordRunnar implements Runnable {
  private String tempImageUrl;
  
  public RecordRunnar(String tempImageUrl) {
      this.tempImageUrl = tempImageUrl;
  }
  
  @Override
  public void run() {
      SlideImageRecordEntity record = new SlideImageRecordEntity();
      record.setCreateTime(new Date());
      record.setHisImgUrl(this.tempImageUrl);
      baseMapper.insertImageRecord(record);
  }
}

实体设计

@Data
public class SlideEntity implements Serializable {
  private Long id;
  /**
  * 随机图片大小
  */
  private Integer rdmLen;
  /**
  * 默认图片名称默认前缀:slide_img_
  */
  private String imgPrefix;
  /**
  * 图片集合
  */
  private List<SlideImageEntity> imgList;
}
@Data
public class SlideImageRecordEntity implements Serializable {
  private long id;
  // 历史图片地址
  private String hisImgUrl;
  private Date createTime;
}

生成滑块小图和带阴影的大图关键代码

随机图片宽度参数说明

javascript">String xwCode = java.util.UUID.randomUUID().toString();
redisClient.setex(SiteConst.Cache.PORTAL_LOGIN_IMAGE_XWIDTH + ":" + xwCode, 5 * 60, widthRandom + "");

每次用户登录时,后台通过 redis设置临时随机图片宽度 xwidth 到缓存(类似与session 会话,保存用户会话参数),用于与前端用户滑块移动宽度比对验证。

同时设置临时随机图片宽度参数:xwidth,过期时间为 5 分钟。

随机小图说明

随机生成的小图 BufferedImage 对象通过 base64 算法加密成一个密码串,

java">/**
* 图片转BASE64
*
* @param image
* @return
* @throws IOException
*/
public static String getImageBASE64(BufferedImage image) throws IOException {
    byte[] imagedata = null;
    ByteArrayOutputStream bao = new ByteArrayOutputStream();
    ImageIO.write(image, "png", bao);
    imagedata = bao.toByteArray();
    Base64 encoder = new Base64();
    String BASE64IMAGE = encoder.encodeAsString(imagedata).trim();
    // String BASE64IMAGE=encoder.encodeBuffer(imagedata).trim();
    BASE64IMAGE = BASE64IMAGE.replaceAll("\r|\n", "");
    return BASE64IMAGE;
}

用于前端页面通过 img 网页标签把 base64 的加密串渲染出来

base64 串渲染格式

<img src="data:image/png;base64, 加密串/>

滑块图片用户拼装宽度校验接口设计

/slide/v1/opi/check-width/{moveLength}/{xwc}

登录验证码

在前端滑块验证通过后,在用户触发登录接口时,需要把请求参数 vc 传入服务网关进行验证码验证。

javascript">//生成验证码
String verfiyCode = java.util.UUID.randomUUID().toString();
redisClient.setex(SiteConst.Cache.PORTAL_VERIFY_CODE + ":" + verfiyCode, 5 * 60, verfiyCode);
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("vc", verfiyCode); // 登录验证码
dataMap.put("xw", xWidth); // 实际图片距离

同时设置登录验证码:verfiyCode,过期时间为 5 分钟。

Docker/K8s

一般微服务基于 docker/k8s 容器化部署,所以考虑单个微服务多节点实例部署,需要考虑数据共享问题,所以不管是随机图片 xwidth 以及登录验证码采用redis 替代 session 会话方式改动成本最小。

Zuul 网关验证:利用网关登录接口方法

在校验登录前,先判断滑块登录验证码 vc 参数是否合法。

验证规则是利用客户端传值验证码与缓存验证码值比较,如果不相等,直接返回验证码校验错误,登录失败。

@ResponseBody
@RequestMapping(value = "/login", method = RequestMethod.POST)
public R login(HttpServletRequest request) {
    //图形验证码
    String vc = request.getParameter("vc");
    if (StringUtils.isNotEmpty(vc)) {
        //portal:vc
        String vcKey = "portal:vc:" + vc;
        boolean captcha = authenticationService.captcha(vcKey, vc);
        if (!captcha) {
            return R.error(ResponseCode.VALIDATION_ERROR);
        }
    }
}

推荐阅读

  • 扛不住 1W+ 并发流量请求,SpringCache 缓存注解真的那么弱?

  • 利用java线程池技术,从MySQL往Elasticsearch导入海量数据

  • 一文读懂阿里大中台、小前台战略

  • jsp的10年是谁让它如此落幕?

 

Java 技术经理一枚,头条付费专栏《Spring Cloud Alibaba微服务实战match》作者,擅长微服务&分布式、SpringCloud&SpringBoot、工作流。

                     

后台回复 1024 免费领取微服务、微信小程序、面试等视频资料,扫描上图微信二维码(WooolaDuang)进微信群


http://www.niftyadmin.cn/n/1240844.html

相关文章

推一款基于原生的小程序(埋点)插件:ani-weapp

推一款基于原生的小程序插件&#xff1a;ani-weapp 真的可以提供太多方便 用最简单的方式实现跨组件实时通信&#xff0c;路由拦截&#xff0c;页面监听&#xff0c;storage管理&#xff0c;防抖节流区域化 最最最重要的一点&#xff1a; 引入真的简单&#xff01;&#xff…

华为改密码让等24小时_华为手机锁屏密码忘记了如何解决 华为手机锁屏密码忘记了解决方法【介绍】...

华为、荣耀很多款机型都配备了指纹识别模块&#xff0c;长期用指纹来解锁&#xff0c;恐怕锁屏密码都忘记了吧&#xff1f;那么要怎么才能不用双清、不用还原系统&#xff0c;不丢失任何数据的情况下修改锁屏密码呢&#xff1f;下面小编来教大家如何用华为云服务的手机找回功能…

记一次 base64 图片存储引发后端查询接口性能断崖式下降问题全程解析

点击上方蓝色“架构荟萃”关注我们&#xff0c;输入1024&#xff0c;你懂的 问题回顾 同事小赵接到客户导入新闻数据要求&#xff0c;由客户提供新闻数据。于是&#xff0c;小赵通过 SQL 脚本入库新闻数据后&#xff0c;发现前台展示新闻特别慢。幸好是晚上凌晨 1 点&#xff0…

小程序canvas多行文本绘制

简单封装了一个微信小程序端绘制多行文本的功能 该功能是基于小程序canvas2D api进行绘制 可以实现&#xff1a; 自动绘制多行文本多行文本上下&#xff0c;左右&#xff0c;居中对齐功能设置最大行数&#xff0c;超出显示省略号设置最大宽度&#xff0c;超出自动换行行间距…

启动模拟器要20多分钟_和平精英模拟器电脑版,画面卡死卡顿几秒且偶尔有电流声...

合理设置模拟器可以解决这些问题&#xff0c;还有一个问题就是网络或服务器不稳定引起&#xff0c;可以试试经过加速器启动模拟器&#xff0c;如果依然有卡顿问题&#xff0c;就要修改一下模拟器相关设置。1、引擎设置&#xff1a;勾选DX&#xff0c;启动渲染缓存等勾选&#x…

前端防止浏览器访问旧版 js 和 css 的优化思路

点击上方蓝色“架构荟萃”关注我们&#xff0c;输入1024&#xff0c;你懂的 前言 最近发版前端项目&#xff0c;用户经常反馈新添加功能在线上环境不好用&#xff0c;常出现新老页面并存的状况。 经前端同事排查发现&#xff0c;实际上只需要重新刷新一下页面就没事了。但是每次…

微信小程序canvas绘制插件

针对小程序新推出的canvas 2d api 简单封装了几个常用功能&#xff0c;用于应付日常海报快捷生成等用途。 <canvas id"myCanvas" type"2d"></canvas>创建canvas const myCanvasawait new AniCanvas(myCanvas)myCanvas输出参数&#xff1a; ca…

cad插件_CAD插件迷你建筑工具箱安装教程

插件下载[名称]&#xff1a;CAD插件-迷你建筑工具箱[大小]&#xff1a;14.9 MB [语言]&#xff1a;简体中文 [安装环境]&#xff1a;Win7/Win8/Win10[支持版本]&#xff1a;CAD2004—2020[32/64位下载链接]&#xff1a;pan.baidu.com/s/16aJpMaLBw3GezKuufP0lfA [提取码]: bye…