Java 图片验证码需求分析

这篇具有很好参考价值的文章主要介绍了Java 图片验证码需求分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java 图片验证码需求分析,java,开发语言

💗wei_shuo的个人主页

💫wei_shuo的学习社区

🌐Hello World !


图片验证码

需求分析

Java 图片验证码需求分析,java,开发语言

  • 连续因输错密码而登录失败时,记录其连续输错密码的累加次数;若在次数小于5时,用户输入正确的密码并成功登录,则次数被清零
  • 连续5次因输错密码而登录失败后,系统弹框提示【您已连续5次输入错误的密码,暂时不允许登录,请10分钟后再次尝试登录】;点击提示框中的【确定】按钮,提示框被关闭
  • 10分钟内再次尝试登录,则系统弹框提示【您已连续5次输入错误的密码,暂时不允许登录,7分43秒后可再次尝试登录】;点击提示框中的【确定】按钮,提示框被关闭;注:提示框中的剩余时间动态倒数至0分0秒
  • 10分钟后,用户可再次尝试登录;此时,若用户在输错密码次数小于5次时成功登录,则其连续输错密码的次数、曾被锁定1次的信息被清空归零;反之,若用户再次连续5次输错密码,则系统弹框提示【您已连续10次输入错误的密码,账号已被锁定、不允许登录,请联系管理员解锁】;点击提示框中的【确定】按钮,提示框被关闭。此后,用户每次用该账号尝试登录时,均弹出此提示框。此时,在运营端,该用户详情页面中的【登录状态】已被自动切换为【锁定】。用户须主动联系莫族密运营人员,运营人员确认用户没有被盗号、遭遇网络攻击等风险后,主动将其【登录状态】置为【解锁】;此时,用户连续输错密码的次数、曾被锁定2次的信息被清空归零
  • 用户登录时,须输入正确的【验证码】
  • 若用户看不清,则可点击【看不清?换一张】字样,也可直接点击验证码部件,点击后自动刷新验证码
  • 点击【登录】按钮后,【用户名】、【密码】、【验证码】这3项但凡有1项校验不通过,则登录失败,【用户名】、【密码】、【验证码】框中已录入的内容被清空,验证码自动刷新
  • 点击【登录】按钮后,若【用户名】、【密码】校验通过,唯独【验证码】校验不通过,则登录失败的系统提示内容为【验证码错误,请重新录入验证码】。同时验证码自动刷新。
  • 【验证码】的有效时间为60秒,超过之后则失效,但不自动刷新。失效之后若录入正确的【用户名】【密码】同时录入页面上已失效的【验证码】,则登录失败,且登录失败的系统提示内容为【验证码错误,请重新录入验证码】,同时验证码自动刷新

实施

验证码接口 | 请求头方式传递
  • 依赖导入
        <!-- 添加图形验证码依赖 -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-captcha</artifactId>
            <version>5.8.5</version>
        </dependency>
  • 图片验证码接口编写
    /**
     * 生成验证码图片
     * @return
     */
    @ApiOperation("获取图形验证码")
    @GetMapping("/identifyImage")
    public Result<String> identifyImage(HttpServletResponse response,
                                        @ApiParam(value = "图形验证码id,无值:生成验证码,有值:刷新验证码")
                                        @RequestParam(name = "codeId", required = false) String codeId) throws IOException {
		// 创建验证码,设置宽、高、长度、干扰线数量
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 90, 4, 100);
        // 获取验证码字符串,赋值code
        String code = lineCaptcha.getCode();
        if (codeId == null) {
            // IdWorker.getId():IdWorker工具类生成唯一ID,并转换成String类型
            codeId = String.valueOf(IdWorker.getId());
            // 将codeId、code.toUpperCase()、过期时间60秒:存储入Redis中
            // code.toUpperCase():code装换成大写形式存储
            redisOps.set(codeId,code.toUpperCase(),60);
        } else {
            redisOps.set(codeId,code.toUpperCase(),60);
        }
        // 将图片验证码codeId设置请求头中
        response.setHeader("codeId", codeId);
        // 获取向客户端发送响应数据的输出流
        try (ServletOutputStream outputStream = response.getOutputStream()) {
            // 验证码图片数据写入到输出流
            lineCaptcha.write(outputStream);
        } catch (Exception e) {
            throw new AuthException("图形验证码输出错误");
        }
        return Result.succ(codeId);
    }
  • Postman调用测试
http://localhost:9036/api/identifyImage

Java 图片验证码需求分析,java,开发语言

Java 图片验证码需求分析,java,开发语言

验证码接口 | base64方式传递
    /**
     * 生成验证码图片
     * @return
     */
    @ApiOperation("获取图形验证码")
    @GetMapping("/identifyImage")
    public Result<IdentifyImageResp> identifyImage(HttpServletResponse response,
                                                   @ApiParam(value = "图形验证码id,无值:生成验证码,有值:刷新验证码")
                                        @RequestParam(name = "codeId", required = false) String codeId) throws IOException {
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 90, 4, 100);
        String code = lineCaptcha.getCode();
        if (codeId == null) {
            codeId = String.valueOf(IdWorker.getId());
            redisOps.set(codeId,code.toUpperCase(),60);
        } else {
            redisOps.set(codeId,code.toUpperCase(),60);
        }
        IdentifyImageResp identifyImageResp = new IdentifyImageResp(codeId, lineCaptcha.getImageBase64Data());
        return Result.succ(identifyImageResp);
    }

Java 图片验证码需求分析,java,开发语言

登录接口
  • 登录接口编写
@PostMapping("login")
@ApiOperation("用户登录")
public Result login(@Validated @RequestBody LoginRequest request) {
    // request.getCodeId():请求体中获取codeId
    // redisOps.get(request.getCodeId():codeId为键,获取redis中对应的值
    String codeId = (String) redisOps.get(request.getCodeId());
    if (codeId.isEmpty()){
        throw new AuthException("验证码已过期请刷新重试");
    }
    AuthContext login = authService.login(request);
    
    // 登录成功后,通过 login.getMerchant() 获取到登录的用户对象,跟新登录信息
    Merchant merchant = login.getMerchant();
    merchant.setLastLoginAt(merchant.getLoginAt());
    merchant.setLoginAt(new Date());
    merchant.setLastLoginIp(merchant.getLoginIp());
    merchant.setLoginIp(CommonTools.getIp(httpServletRequest));
    merchantRepo.updateById(merchant);
    login.setMerchant(merchant);
    // JsonMapper.objectToJson(login):将login对象转换成 JSON 格式的字符串
    log.info("LOGIN - > {}", JsonMapper.objectToJson(login));
    return Result.succ("登录成功");
}
  • LoginRequest.java:请求体字段
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginRequest {

    @NotEmpty
    @ApiModelProperty("登录名")
    private String username;
    @NotEmpty
    @ApiModelProperty("密码,md5加密全小写")
    private String password;
    @ApiModelProperty("验证码")
    private String code;
    @ApiModelProperty("验证码Id")
    private String codeId;

}
  • AuthService.java
    public AuthContext login(LoginRequest login) {
        // 登录验证和处理
        if (StringUtils.isBlank(login.getUsername())) {
            throw new AuthException("用户名不能为空");
        }
        if (StringUtils.isBlank(login.getPassword())) {
            throw new AuthException("密码不能为空");
        }
        // 缓存清空,登出操作
        logout();
        Merchant merchant = findMerchantByLoginEmail(login.getUsername());
        if (merchant == null) {
            authError("账户不存在,或状态不正确");
        } else if (merchant.getIsLocked()) {
            authError("账户已停用");
        }
        // 从redis获取login.getUsername()+"lock-time")的键对应的值
        if (redisOps.get(login.getUsername()+"lock-time") != null){
            // redisOps.getExpire:获取 Redis 中指定键的过期时间
            long expire = redisOps.getExpire(login.getUsername() + "lock-time");
            // 转换为分钟
            int minutes = (int) (expire / 60);
            // 转换为秒钟
            int seconds = (int) (expire % 60);
            authError("您已连续5次输入错误的密码,暂时不允许登录,"+minutes+"分"+seconds+"秒后可再次尝试登录");

        }
        System.out.println(merchant.getLoginPassword());
        System.out.println(SecretUtils.encrypt(login.getPassword()));
        Integer errorNum = (Integer) redisOps.get(login.getUsername());
        if (!merchant.getLoginPassword().equals(SecretUtils.encrypt(login.getPassword()))) {
            //密码错误次数为null时创建键值对
            if (errorNum == null){
                redisOps.set(login.getUsername(),1);
            }else if  ((errorNum > 0 && errorNum < 4) || (errorNum > 5 && errorNum < 10)){
                //密码错误次数为0-4、5-10时incr
                redisOps.incr(login.getUsername(),1);
            }else if (errorNum+1==5){
                //密码错误次数为5时锁定10分钟
                redisOps.set(login.getUsername()+"lock-time","lock",600);
                authError("您已连续5次输入错误的密码,暂时不允许登录,请10分钟后再次尝试登录");
            }else {
                //密码错误次数为10时锁定
                merchant.setIsLocked(true);
                merchantRepo.updateById(merchant);
                authError("您已连续10次输入错误的密码,账号已被锁定、不允许登录,请联系管理员解锁");
            }
            authError("密码不正确");
        }
        String code= (String) redisOps.get(login.getCodeId());
        if (code == null || login.getCode()==null || !code.equals(login.getCode().toUpperCase())){
            authError("请输入正确的验证码");
        }
//        merchant.setLoginPassword("*");
        String token = Sha.sha256(UUID.randomUUID().toString());
        AuthContext authContext = new AuthContext(token, merchant, null);
        redisOps.set(token, JsonMapper.objectToJson(authContext), authProp.getExpiresSeconds());
        CookieUtils.setCookie(response, "/", authProp.getTokenHeader(), token, authProp.getExpiresSeconds());
        //登陆完成删除账号错误次数
        if (errorNum!=null)
            redisOps.delete(login.getUsername());
        return authContext;
    }

    public String logout() {
        String cookie = CookieUtils.getCookie(request, authProp.getTokenHeader());
        String token = StringUtils.isNotBlank(cookie) ? cookie : request.getHeader(authProp.getTokenHeader());
        if (StringUtils.isNotBlank(token)) {
            redisOps.delete(token);
        }
        return "登出成功";
    }

    private void authError(String errorMsg) {
        throw new AuthException(errorMsg);
    }
  • Postman测试

Java 图片验证码需求分析,java,开发语言


🌼 结语:创作不易,如果觉得博主的文章赏心悦目,还请——点赞👍收藏⭐️评论📝


Java 图片验证码需求分析,java,开发语言文章来源地址https://www.toymoban.com/news/detail-712774.html

到了这里,关于Java 图片验证码需求分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【java】opencv + Tesseract(tess4j) 实现图片处理验证码识别

    2022/12/27 有的小伙伴说maven导入不了依赖,加了一种方法,百分百解决。 2022/12/28 写了半天,想去论坛放松休息下,结果看到别人已经有成品了,难受啊马飞,晚点看情况要不要写个搭建使用方法(我猜没人看,估计也不用写了,就当自己做个记录) 2023/3/24 更新了一键部署验

    2024年02月08日
    浏览(67)
  • 【Java 进阶篇】Java Web开发:实现验证码功能

    在Web应用程序中,验证码(CAPTCHA)是一种常见的安全工具,用于验证用户是否为人类而不是机器。验证码通常以图像形式呈现,要求用户在登录或注册时输入正确的字符。在这篇文章中,我们将详细介绍如何在Java Web应用程序中实现验证码功能。 验证码是“全自动区分计算机

    2024年02月03日
    浏览(40)
  • java对接打码平台用selenium实现对图片验证码识别(对接文档看这一个就够了)

    在很多平台软件中,咱们登录之后都有一些验证,例如图片数字验证,还有现在流行的滑块验证码,点选验证码,这么复杂的事情,我们程序员当然要用程序的方式解决啦,所以也有一些平台提供了快捷验证的方式,在这里,博主就给大家分享一下,如何实现对图片数字的识

    2023年04月25日
    浏览(71)
  • 用java语言写一个网页爬虫 用于获取图片

    以下是一个简单的Java程序,用于爬取网站上的图片并下载到本地文件夹: 这个程序首先读取指定网址的HTML源码,然后从中提取出所有的图片URL。最后,程序利用 Java 的 IO 功能下载这些图片并保存到指定的本地文件夹中。 需要注意的是,该程序只是一个简单的演示,实际使

    2024年02月11日
    浏览(49)
  • Java开发 微软OAuth身份验证在EWS中的应用

    一、使用说明 看到有朋友在评论区咨询Java通过Oauth2.0调用EWS的实现。所以有了这篇文章,大概思路是使用Azure的客户端账号和密码通过http方式获取到Token信息,再通过Token去初始化ExchangeService实例,再通过各项API完成各种功能的调用。 二、HTTP方式获取Ews的Token信息 配置文件

    2024年02月16日
    浏览(55)
  • JAVA开发(腾讯云OSS图片上传)

    需求背景: 项目中需要上传图片。 存储方式: 使用腾讯云的OSS组件。 代码实现: 1、使用腾讯云OSS需要使用的参数信息: OSS的域名; OSS的地域节点; OSS存储桶的名称; OSS权限凭证; OSS权限访问秘钥; OSS图片存储策略; 使用的缩略图策略; 允许上传的图片类型; 参数

    2024年02月11日
    浏览(54)
  • 前后端分离java开发图形验证码+谷歌开源Kaptcha使用(Springboot+redis实现图形验证码校验)

    注册 - 登录 - 修改密码 一般需要发送验证码,但是容易被攻击恶意调用。 手机短信轰炸机是批量、循环给手机无限发送各种网站的注册验证码短信的方法。 短信一条5分钱,如果被大盗刷大家自己计算邮箱通知不用钱,但被大盗刷,带宽、连接等都被占用,导致无法正常使用

    2024年01月19日
    浏览(57)
  • 家校互通小程序实战开发01需求分析

    最近几年,随着移动互联网的深入发展,我们的日常生活和工作和微信已经紧密绑定。其实,有时候生活和工作的界限已经不明显,在我们的微信好友里既有家人、朋友,也有同事、客户和领导。 因为微信连接的便利性和沟通的及时性,现在学校也将微信作为和家长沟通和连

    2024年01月15日
    浏览(43)
  • java语言分析区块链钱包生成的原理

    java语言分析区块链钱包生成的原理: 一、区块链钱包实现的技术原理用大概就是: 钱包助记词生成了种子,种子发芽结果,果实就是私钥,私钥推导出了公钥,公钥数据的节选部分成了钱包地址。同时钱包提供了Key Store,他也是私钥加密后的文件为了配合正常的密码使用,

    2024年01月17日
    浏览(46)
  • Java GUI开发的几个小工具:apk/aab签名,验证签名,aab转apk

    平时经常给apk/aab签名,验证签名,aab转apk等操作,每次输入命令行十分繁琐。于是利用JAVA GUI简单开发了几个jar包界面化工具,提供给大家一起使用。 工具 功能 JarSignerTool.jar 为apk/aab签名 ApkSignerTool.jar 为apk签名 AppSignVerifyTool.jar 验证apk/aab的签名 CheckSignFileTool.jar 查看签名文件

    2024年02月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包