Spring Boot整合zxing实现二维码登录

zxing是google的一个二维码生成库,使用时需配置依赖:

Groovy 复制代码
implementation("com.google.zxing:core:3.4.1")
implementation("com.google.zxing:javase:3.4.1")

zxing的基本使用

我们可以通过MultiFormatWriter().encode()方法获取一个matrix对象:

Kotlin 复制代码
val matrix = MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hint)

这个方法接受5个参数,按照顺序解释如下:

  1. 二维码的字符串内容
  2. 格式,如要生成二维码,则需传入BarcodeFormat.QR_CODE
  3. 二维码宽度(像素)
  4. 二维码高度(像素)
  5. 二维码的属性

其中,第5个参数需要传入一个HashMap对象:

Kotlin 复制代码
private val hint = mapOf(
    // 误差校正等级
    EncodeHintType.ERROR_CORRECTION to ErrorCorrectionLevel.M,
    // 字符集
    EncodeHintType.CHARACTER_SET to "UTF-8",
    // 外边框像素
    EncodeHintType.MARGIN to 5
)

需要指定三个键,第一个键的值是误差校正等级,在ErrorCorrectionLevel枚举中,有如下选择:

  • L:可以校正7%
  • M:可以校正15%
  • Q:可以校正25%
  • H:可以校正30%

误差校正等级的存在,可以使二维码被遮挡时,仍然能够被正常扫描。一般来说,误差校正等级越大,二维码就越大

第二个键是字符集,一般用UTF-8即可

第三个键是外边框的像素大小

整合Spring Boot

首先我们需要有一个二维码生成的工具类,可以生成将二维码并将二维码输出至一个输出流:

Kotlin 复制代码
package com.example.qrcode.util

import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.MultiFormatWriter
import com.google.zxing.client.j2se.MatrixToImageWriter
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
import java.io.OutputStream

object QRUtil {

    private val width = 400
    private val height = 400
    private val hint = mapOf(
        // 误差校正等级
        EncodeHintType.ERROR_CORRECTION to ErrorCorrectionLevel.M,
        // 字符集
        EncodeHintType.CHARACTER_SET to "UTF-8",
        // 外边框像素
        EncodeHintType.MARGIN to 5
    )

    /**
     * 创建二维码并写入到输出流
     * @param content 二维码内容
     * @param outputStream 输出流
     * */
    fun writeCodeIntoStream(content: String, outputStream: OutputStream){
        val matrix = MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hint)
        MatrixToImageWriter.writeToStream(matrix, "png", outputStream)
    }

}

接下来我们需要一个控制器类,提供电脑生成二维码的登录接口,手机扫描二维码使设备登录的接口,和手机扫描二维码后,电脑登陆成功,跳转的接口:

Kotlin 复制代码
package com.example.qrcode.controller

import com.example.qrcode.util.QRUtil
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import jakarta.servlet.http.HttpSession
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.net.URL

@RestController
class QRLoginController {

    val idLogin = HashMap<String, Boolean>()

    @RequestMapping("/QR/login")
    fun login(request: HttpServletRequest, response: HttpServletResponse, session: HttpSession){
        if (idLogin.containsKey(session.id) && idLogin[session.id] == true){
            response.sendRedirect("/QR/login/down")
            return
        }
        response.setIntHeader("Refresh", 1)
        val strUrl = request.requestURL.toString()
        val url = URL(strUrl)
        val host = url.host
        val pro = url.protocol
        QRUtil.writeCodeIntoStream("$pro://$host/QR/login/${session.id}", response.outputStream)
    }

    @RequestMapping("/QR/login/{id}")
    fun loginByID(@PathVariable("id") id: String): String{
        idLogin[id] = true
        return "登录中"
    }

    @RequestMapping("/QR/login/down")
    fun loginDown(): String{
        return "登录成功"
    }

}

在/QR/login接口中,我们首先判断当前会话是否已经被人扫了二维码,如果是,则重定向到/QR/login/down接口中;而如果不是,则会通过设置响应头"Refresh"参数,使电脑浏览器端每个一秒刷新一下,并向电脑输出一个二维码,手机扫描这个二维码后,将会前往/QR/login/{id}接口,并通过可变的URL路径,将id传入。

在/QR/login/{id}接口中,将会将传入的id的登录状态设置为真。这样的话,电脑端访问的/QR/login接口就会跳转至/QR/login/down接口

要注意,这里面的实现方式不是正常的实现方式。正常的实现方式应通过前端的脚本语言实现登录状态的刷新。但是因为我们没有前端,所以采用了这种方法

由于手机扫描二维码时,不会指定访问端口,因此需要在application.properties中,配置服务器的端口:

Kotlin 复制代码
server.port=80

测试一下

使用浏览器访问http://[你的IP地址]/QR/login,注意,这里不能通过127.0.0.1或localhost访问,因为需要手机和电脑两个设备访问

这时,浏览器会显示一个二维码(CSDN可能不让上传二维码,因此进行了手动打码):

接下来使用手机扫描这个二维码,会发现浏览器成功的跳转到了登录成功的页面:

因此,我们的二维码登录就成功实现了

相关推荐
风筝在晴天搁浅5 分钟前
hot100 78.子集
java·算法
故事和你911 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
Configure-Handler2 小时前
buildroot System configuration
java·服务器·数据库
:Concerto2 小时前
JavaSE 注解
java·开发语言·sprint
JMchen1233 小时前
现代Android图像处理管道:从CameraX到OpenGL的60fps实时滤镜架构
android·图像处理·架构·kotlin·android studio·opengl·camerax
电商API_180079052473 小时前
第三方淘宝商品详情 API 全维度调用指南:从技术对接到生产落地
java·大数据·前端·数据库·人工智能·网络爬虫
一点程序3 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
C雨后彩虹3 小时前
计算疫情扩散时间
java·数据结构·算法·华为·面试
2601_949809593 小时前
flutter_for_openharmony家庭相册app实战+我的Tab实现
java·javascript·flutter
vx_BS813304 小时前
【直接可用源码免费送】计算机毕业设计精选项目03574基于Python的网上商城管理系统设计与实现:Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制
java·python·课程设计