react使用谷歌人机验证

在项目中,需要对请求验证,防止被爆破,这里使用的是谷歌的recaptcha-v3。

1.申请谷歌人机验证的api

申请链接,申请完后需要将两个谷歌颁发的key分别写入前,后端的配置环境中,后面会使用.

 2.前端部分

 前端使用的是vite+CRA框架,先放出配置.

vite全局环境配置(vite.config.js)(环境配置记录,验证请看下面).
import { defineConfig, loadEnv } from 'vite'
import ViteTestConfig from './config/vite.test.config.js'
import ViteBaseConfig from './config/vite.base.config.js'// 策略模式做一个动态的配置
const envResolver = {"build": () => {console.log("生产环境")return ({ ...ViteTestConfig, ...ViteBaseConfig })},"serve": () => {console.log("开发环境")// 另一种写法// return Object.assign({}, ViteBaseConfig, ViteDevConfig)return ({ ...ViteTestConfig, ...ViteBaseConfig })}}// https://vitejs.dev/config/
export default defineConfig(({ command, mode }) => {const env = loadEnv(mode, process.cwd(), "")console.log("env : ", env)// 根据不同的环境使用不同的配置文件,注意这个地方的写法,非常的奇特return envResolver[command]()}
)

这里使用动态配置vite的环境,vite的config文件,当前使用的是本地开发环境使用的是vite.test.config.js,其他环境按这样引用就好了,环境配置比如host,prot,dir等等都在自己需要的环境config中配置就行了.

同时还需要配置环境变量,环境变量使用.env文件,这里我创建了个env文件夹然后将环境变量都放进去了,需要在vite的环境配置中告诉其环境变量文件位置.

import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"
export default defineConfig({plugins: [react()],envDir: 'src/env',
})

同时也分各种不同的环境变量配置,格式为:.env.(环境名称) 例如:..env.development

而.env则是默认的环境变量,也可以理解为全局变量,不管你加不加载都会读取其中的变量.

而vite中的变量命名必须以 VITE_ 开头,否则不会读取

例子:

VITE_TEST_BASE_URL="http://127.0.0.1:8080/api"

在react中读取变量(react数据共享)

react讲究一个纯函数,所以变量声明只能在其组件中使用,这就有一个问题,当我们使用主题或者存储用户token的时候就不能在所有组件中共享,如果一个个传递下去非常麻烦,所以需要使用到react提供的useContext.

1.创建一个context载体组件

// AppContext.js
import React from 'react'const AppContext = React.createContext()export default AppContext

2.在父组件中使用

function App() {
// 主题模式const [styleMode, setStyleMode] = React.useState('light')//改变页面主题const changeMode = () => {const newMode = styleMode === 'dark' ? 'light' : 'dark'setStyleMode(newMode)localStorage.setItem('theme', newMode)}//主题const customTheme = createTheme({palette: {mode: styleMode,},})<ThemeProvider theme={customTheme}><AppContext.Providervalue={{ mode: styleMode, changeMode }}>{ElementRouter}</AppContext.Provider></ThemeProvider>
}

使用该方式可以将变量在被包裹的组件中使用,同时也可以传递函数,对父组件中的数据进行修改。

3.子组件调用

直接使用useContext(载体组件名)即可获得变量

//获取全局变量

const { mode, changeMode } = useContext(AppContext)

//获取环境变量

const variable= import.meta.env.定义的环境变量名

在前端引入recaptcha v3

这里使用封装好的组件引入,npm安装

npm install react-google-recaptcha-v3

v2的话需要自己去找一下引入方式,此方法只适合v3.

引入后在需要引入谷歌验证的父组件上对子组件进行包裹,这里我直接放在APP组件上,直接全部使用了.

function App{return (<ThemeProvider theme={customTheme}><GoogleReCaptchaProviderreCaptchaKey={import.meta.env.VITE_GOOGLE_CAPCHAT_KEY}//国内谷歌验证useRecaptchaNet={true}><AppContext.Providervalue={{ mode: styleMode, baseUrl: baseUrl, changeMode }}>{ElementRouter}</AppContext.Provider></GoogleReCaptchaProvider></ThemeProvider>)
}

key就是你申请到的前端key(client),useRecaptchaNet一定要开,不开的话会去访问谷歌的verifty,局域网内是无法访问的.

使用的话v3使用的是一个无感验证,不需要用户去进行图片或者人机验证点击,所以直接封装一个验证逻辑后放入代码中就好了(比如提交表单的时候或者点击某些按钮的时候等等)

import { requestSlimpePost } from "./RequestUtils"async function checkRobot (executeRecaptcha, baseUrl) {//人机验证不可用情况if (!executeRecaptcha) {alert('人机验证不可用,请检查网络!')return false}//获得验证tokenconst capChatToken = await executeRecaptcha()//获取token失败if (!capChatToken) {alert('人机验证失败!')return false}//封装成json数据const data = {capChatToken: capChatToken,}const jsonData = JSON.stringify(data, null, 2)//获取返回数据const res = await requestSlimpePost(baseUrl + '/verify/recapchat', jsonData)if (res.msg != 'ok' || res.code != 200) {alert('人机验证失败!')console.log(res)return false}return true
}export { checkRobot }

其中requestSlimpePost是我自己封装的请求工具,就使用fetch就不过多介绍了.

 const { executeRecaptcha } = useGoogleReCaptcha()const { baseUrl } = React.useContext(AppContext)const handleSubmit = async (event) => {event.preventDefault()//获取当前登录数据const userInputData = new FormData(event.currentTarget)const userName = userInputData.get('userName')const passwd = userInputData.get('passwd')if (!userName) {alert('用户名不能为空')return}if (!passwd) {alert('密码不能为空')return}const notRobot = await checkRobot(executeRecaptcha, baseUrl)if (!notRobot) return}

先通过封装的包中获取executeRecaptcha这个对象,然后通过调用其中函数向谷歌验证申请验证令牌,拿到后再通过后端携带该令牌去进行评测.

3.后端部分

在前端获取验证令牌后,需要向后端申请验证,后端则向谷歌申请该次人机验证的评分,并进行逻辑操作.

/*** @author Vermouth* @ClassName: ReCapChatManager* @Description: 人机校验管理器* @Date 2024/4/10 11:05* @Version: V1.0*/
@Component
public class ReCapChatManager {// 请求地址private static final String SITEVE_RIFY = "https://www.recaptcha.net/recaptcha/api/siteverify";private static OkHttpClient httpClient = new OkHttpClient();@Autowiredprivate ReCapIpManager reCapIpManager;// 从配置文件中读取到后端key@Value("${recaptcha.server-key}")private String serverKey;/*** 人机校验** @param request 请求包装类* @return true / false* @throws IOException*/public boolean robotCheck(HttpServletRequest request) throws IOException {//请求的IPString remoteAddr = RequestUtils.getClientIp(request);String requestJson = StringUtils.bufferToString(request.getReader());JsonObject requestObj = JsonParser.parseString(requestJson).getAsJsonObject();//异常的请求也驳回if (null == requestObj) {this.addFreezeIp(remoteAddr);return false;}//请求体设置RequestBody formBody = new FormBody.Builder().add("secret", this.serverKey)  //服务端key.add("response", requestObj.get("capChatToken").getAsString())   //客户端提交的token//.add("remoteip", remoteAddr)  //客户的ip地址,不是必须的参数。.build();//请求头设置Headers reqHeaders = new Headers.Builder().add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=UTF-8").add(HttpHeaders.CONTENT_LENGTH, String.valueOf(formBody.contentLength())).build();//装入请求中Request reRequest = new Request.Builder().url(SITEVE_RIFY).headers(reqHeaders).post(formBody).build();Call call = httpClient.newCall(reRequest);String responseData = null;try {//发起请求Response googleResponse = call.execute();//检查是否获取到响应体if (null == googleResponse.body()) throw new IOException();responseData = googleResponse.body().string();} catch (IOException e) {throw new SystemException(ExceptionStatus.OKHTTP_CALL_EXCEPTION_);}JsonObject jsonObject = JsonParser.parseString(responseData).getAsJsonObject();//TODO 后续有了服务器还需接入Cloudflare!!!!// 是否执行成功if (!jsonObject.get("success").getAsBoolean()) {// 在失败的情况下,获取到异常状态码JsonArray errorCodes = jsonObject.get("error-codes").getAsJsonArray();this.addFreezeIp(remoteAddr);return false;}//获取评分double score = jsonObject.get("score").getAsDouble();if (score < 0.5) {// 如果低于0.5分,服务不接受该请求this.addFreezeIp(remoteAddr);return false;}return true;}/*** 冻结ip操作** @param ipAddress 需冻结ip*/public void addFreezeIp(String ipAddress) {reCapIpManager.freezeIp(ipAddress);}}

需要注意的是请求地址,请求地址同样也必须是国内的谷歌验证api,否则访问不到.

一般来说打分都是在0.9,我自己测试的都是在0.9,可以根据自己的情况来调整判断人机的分数.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/6149.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python | Leetcode Python题解之第64题最小路径和

题目&#xff1a; 题解&#xff1a; class Solution:def minPathSum(self, grid: List[List[int]]) -> int:if not grid or not grid[0]:return 0rows, columns len(grid), len(grid[0])dp [[0] * columns for _ in range(rows)]dp[0][0] grid[0][0]for i in range(1, r…

All In ai,Oracle 23C没了,等来了Oracle 23ai

今年一月份的Blog介绍Oracle命名规则的时候&#xff0c;说到Oracle的命名是紧紧跟随时代浪潮的前言科技的&#xff0c;在文章的最后还大胆预测也许Oracle的下一个版本就叫25A了&#xff0c;结果Oracle根本等不及&#xff0c;把原来已经海量宣传的Oracle 23C直接改名为23ai&…

分布式与一致性协议之Raft算法(四)

Raft算法 Raft是如何解决成员变更问题的 在日常工作中&#xff0c;你可能会遇到服务器故障的情况&#xff0c;这时你需要替换集群中的服务器。如果遇到需要改变数据副本数的情况&#xff0c;则需要增加或移除集群中的服务器。总的来说&#xff0c;在日常工作中&#xff0c;集…

如何基于nginx搭建https网站

华子目录 使用nginx的http_ssl模块建立加密传输的网站查看配置文件ssl配置文件的主要参数实验&#xff1a;搭建nginxssl加密认证的web服务器 使用nginx的http_ssl模块建立加密传输的网站 查看 [rootserver ~]# nginx -V #查看是否有--with-http_ssl_module模块&#xff0c;如…

AI时代,如何让ChatGPT成为你最好的编程老师|TodayAI

ChatGPT作为生成式预训练变换器&#xff08;GPT&#xff09;系列模型的一种&#xff0c;专门设计用来理解和生成文本&#xff0c;其生成的文本能够高度模仿人类的对话方式。这种能力不仅让它在进行日常对话时表现得像极了真人&#xff0c;还使其在各种专业领域内&#xff0c;比…

TCP四次挥手分析

TCP四次挥手分析 概念过程分析为什么连接的时候是三次握手&#xff0c;关闭的时候却是四次握手&#xff1f;为什么要等待2MSL&#xff1f; 概念 四次挥手即终止TCP连接&#xff0c;就是指断开一个TCP连接时&#xff0c;需要客户端和服务端总共发送4个包以确认连接的断开。 在…

基于深度学习的3D目标检测与跟踪

目标检测和跟踪对于自动驾驶来说是至关重要和基础的任务&#xff0c;旨在从场景中识别和定位出那些预定义类别的对象。在所有形式的自动驾驶数据中&#xff0c;3D点云学习引起了越来越多的关注。目前&#xff0c;有许多用于3D目标检测的深度学习方法。然而&#xff0c;鉴于点云…

【方法】PDF如何取消“限制编辑”?

我们知道&#xff0c;PDF设置“限制编辑”可以用来保护文件&#xff0c;设置后很多功能就会被锁定&#xff0c;比如无法编辑内容&#xff0c;无法打印&#xff0c;另存文件等等&#xff0c;可以看到大多数菜单选项都是灰色状态&#xff0c;无法点击。 那如果后续想要使用锁定的…

【Python快速上手(十一)】

目录 Python快速上手&#xff08;十一&#xff09;Python3 迭代器与生成器迭代器&#xff08;Iterator&#xff09;生成器&#xff08;Generator&#xff09;区别注意事项 Python快速上手&#xff08;十一&#xff09; Python3 迭代器与生成器 迭代器&#xff08;Iterator&am…

启动盘制作

魔术师pe安装教程 我一般使用魔术师来安装windows系统 魔术师pe地址下载 解压后使用 把ios映像文件放入pe系统u盘下 开机按f1,进入bios,将usb接口拉到本电脑&#xff0c;在按f10保存&#xff0c;在按f12即可找到pe的u盘 ventoy安装教程 其他系统安装我使用ventoy ventoy地…

宇宙最强Windows下载神器IDM,还不快用 互联网下载管理器(IDM)全面评测

互联网下载管理器&#xff08;IDM&#xff09;是一款功能强大的下载工具&#xff0c;自 1999 年问世以来&#xff0c;一直以其卓越的性能和稳定性受到用户的喜爱。IDM 可以帮助用户加速下载速度&#xff0c;最高可达 5 倍&#xff0c;同时还具有断点续传、定时下载、自动分类等…

第14章 软件测试过程和管理

一、测试过程模型 &#xff08;一&#xff09;组织级测试过程 用于开发和管理组织级测试规格说明。常用的组织级测试规格说明包括组织级测试方针和组织级测试策略。 &#xff08;二&#xff09;测试管理过程 1、内容 包括测试管理和动态测试。动态测试&#xff1a;测试设计…

Adobe Acrobat Reader DC的基本功能

Adobe Acrobat Reader DC是一款用于查看、打印和注释PDF文件的免费软件。其基本功能包括&#xff1a; 查看和浏览PDF文件&#xff1a;用户可以打开、浏览和查看PDF文件&#xff0c;包括单页和多页视图模式。 打印PDF文件&#xff1a;用户可以通过打印功能将PDF文件打印出来。 …

大数据组件之Storm详解

Storm 是一个免费并开源的分布式实时计算系统&#xff0c;具有高容错性和可扩展性。它能够处理无边界的数据流&#xff0c;并提供了实时计算的功能。与传统的批处理系统相比&#xff0c;Apache Storm 更适合处理实时数据。 让我们深入了解一下 Storm&#xff1a; 1.Storm 简介…

超强动画制作软件blender

blender中文手册&#xff1a;Blender 4.1 Manual Blender 是一款集3D建模、渲染、动画、视频编辑、音频处理、游戏设计等多功能于一体的软件。由于其开源性质&#xff0c;它拥有庞大的用户群体和活跃的开发者社区&#xff0c;这使得Blender的功能和性能得到了不断的提升和优化…

uni-ui 使用uni-icons有些图标显示不出来,如down,up图标

问题描述 我使用的是uni创建时勾选的uni-ui模板&#xff0c;一次偶然机会发现down图标显示不出&#xff0c;left&#xff0c;right等其他图标又可以。 最后发现使用uni-icons不是最新版本导致的&#xff0c;使用模板生成的icons是1.3.5版本&#xff0c;我在插件市场找到的是2.0…

【数学建模】2024五一数学建模C题完整论文代码更新

最新更新&#xff1a;2024五一数学建模C题 煤矿深部开采冲击地压危险预测&#xff1a;建立基于多域特征融合与时间序列分解的信号检测与区间识别模型完整论文已更新 2024五一数学建模题完整代码和成品论文获取↓↓↓↓↓ https://www.yuque.com/u42168770/qv6z0d/gyoz9ou5upv…

NI CRIO 9045 LABVIEW2020

1.labview工程如果要访问CRIO&#xff0c;需要设置以下&#xff0c;否则在项目中连接失败。 2.项目中如果要传文件&#xff0c;需要安装WebDEV 3.使用WebDAV将文件传输到实时(RT)目标 https://knowledge.ni.com/KnowledgeArticleDetails?idkA03q000000YGytCAG&lzh-CN

Redis协议与异步方式

Rredis Pipeline redis pipeline 是一个客户端提供的机制&#xff0c;而不是服务端提供的&#xff1b; pipeline 不具备事务性&#xff1b; 目的&#xff1a;节约网络传输时间&#xff1b; 通过一次发送多次请求命令&#xff0c;从而减少网络传输的时间。 Redis发布订阅 为了支…

selenium-webdriver 设置宽高 node

在使用 Node.js 的 Selenium WebDriver 进行自动化测试时&#xff0c;你可能会需要为浏览器窗口设置特定的宽度和高度。以下是如何设置浏览器窗口大小的示例&#xff1a; 首先&#xff0c;确保你已经安装了 selenium-webdriver 包。如果还没有安装&#xff0c;可以通过运行以下…