首页 > 其他分享 >springboot验证码-GoogleReCaptcha3 ReCaptcha

springboot验证码-GoogleReCaptcha3 ReCaptcha

时间:2023-08-18 23:11:55浏览次数:39  
标签:springboot ReCaptcha GoogleReCaptcha3 验证码 springframework token org import recap

现在的应用中对于登录,注册,短信验证码。。。这些场景来说,验证码真的是必不可少。随着技术的发展,也使得验证码从当初的图形验证码,发展到今天的滑块,倒立文字点击,数学计算,手势滑动,拼图,刮图。。。等等各种花样,总之一个目的,阻止机器人的访问

验证码这玩意儿,确实给用户带来了很不好的体验,很多应用的验证码确实玄乎的很让人让人抓狂。

ReCaptcha

这是谷歌的一个验证码程序,它免费,强大,很多世界级别的应用都在使用它(靠谱)。

它现在有2个比较流行的版本!!

ReCaptcha 2,它长这样

这玩意儿,有时候挺让人烦的,一看到这种验证码,愁得慌。

ReCaptcha 3

没法展示给你看... 是的,没图,没摁钮。这是最高级的一个版本,不骚扰用户。而是偷偷的读取一些客户端的环境数据(具体是啥我也不知道),提交给服务器,最后服务器给出一个数字评分。0 - 1。0 肯定是机器人,1肯定不是。应用需要通过这个评分来决定当前请求是否合法。

这也是这篇文章,要接入的版本,下面,从注册开始,演示一个接入ReCaptcha 3的案例。

注册

不要问为什么打不开下面的这些地址,我也不知道。

注册地址 https://www.google.com/recaptcha/admin/create

很简单,按照自己的需求填写名字,应用的访问域名。即可。

注册成功

有2个密钥,需要记住。第一个叫做前端密钥,会暴露在客户端。第二个叫做后端密钥,用于和远程服务器通信,不能暴露给客户端。

管理控制台

https://www.google.com/recaptcha/admin

控制台可以查看一些验证信息,例如请求数量之类的,很简单,自己看就懂。

文档

https://developers.google.com/recaptcha/intro

更多的细节,可以看看官方文档

创建一个SpringBoot应用

可以从 http://start.springboot.io/ 创建

创建过程就省略了,不需要任何第三方的依赖,基本的SpringBoot依赖就行。

把key配置在yml中

recaptcha:
  client-key: "6LdvzboZAAAAALrLVyjabnd5xfb06izncgK0JXCt"
  server-key: "6LdvzboZAAAAAE1mLwijdq9noxVUbWRBmqm-4Ava"

配置在yml中,程序可以灵活读取

Web客户端集成

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>ReCaptcha V3</title>
		<!-- render参数值就是前端密钥 -->
		<script src="https://www.recaptcha.net/recaptcha/api.js?render=6LdvzboZAAAAALrLVyjabnd5xfb06izncgK0JXCt"></script>
	</head>
	<body>
		<input name="name" placeholder="输入名字"  id="name"/>
		<button id="button">提交</button>
	</body>
	<script type="text/javascript">
		// 前端密钥
		const CLIENT_KEY = "6LdvzboZAAAAALrLVyjabnd5xfb06izncgK0JXCt";
		
		// grecaptcha.ready => 验证码初始化成功后后回调
		grecaptcha.ready(() => {
			console.log('验证码初始化ok');
		});
		
		// 表单提交
		document.querySelector('#button').addEventListener('click', () => {
			
			// grecaptcha.execute => 生成Token
			/**
				第一个参数就是前端key
				第二个参数是一个对象,action属性是一个自定义的“场景名称”。一个APP可以有N个验证场景,在后台可以查看不同场景下的验证数据。
				第三方个参数是回调方法,Token就是形参,一般在这个方法里面发起请求
			**/
			grecaptcha.execute(CLIENT_KEY, {action: 'test'}).then((token) => {
				
				// 构建请求体
				const body = new URLSearchParams();
				body.set('token', token);									// 验证码回调token
				body.set('name', document.querySelector('#name').value);	// 表单数据
				
				// 发起请求
				fetch('/test', {
					method: 'POST',
					body: body
				}).then(resp => {
					if (resp.ok){
						resp.json().then(message => {
							if (message.success){
								document.querySelector('#name').value = '';
							} else {
								alert('人机验证失败');
							}
						})
					}
				});
			});
		});
	</script>
</html>

如果是模版引擎渲染,可以把配置文件中的前端key渲染到页面(这里直接在前端写死的)。

重点的几个东西

js库的加载

<script src="https://www.recaptcha.net/recaptcha/api.js?render={客户端key}"></script>

验证码初始化完成的回调,这不是必须的

grecaptcha.ready(() => {
	console.log('验证码初始化ok');
});

通过执行execute方法,获取到Token

grecaptcha.execute("{客户端key}", {action: '{action}'}).then((token) => {
	// 拿到token后,提交数据给服务器
});

服务器端的验证

验证的步骤

1. 使用Http客户端对远程服务器发起POST请求,有三个参数

https://www.recaptcha.net/recaptcha/api/siteverify
名称说明是否必须
secret 后端key
response 客户端生成的Token
remoteip 客户端ip

2. 服务器响应

{
  "success": true|false,      // 此请求是否是站点的有效reCAPTCHA令牌
  "score": number             // 此请求的分数(0.0-1.0),人机判断的参考值。1 是人类,0是机器。
  "action": string            // 定义的验证场景
  "challenge_ts": timestamp,  // 加载的时间戳(ISO格式yyyy-MM-dd'T'HH:MM:ssZZ)
  "hostname": string,         // 使用reCAPTCHA的站点的主机名
  "error-codes": [...]        // 可选的错误代码
}

错误代码的说明

Error code说明
missing-input-secret secret参数丢失
invalid-input-secret secret参数无效或格式错误
missing-input-response 缺少响应参数
invalid-input-response 响应参数无效或格式错误
timeout-or-duplicate 响应不再有效:太旧或以前使用过。

3. 自己根据评分判断是否要放行

完整的代码

import java.util.Collections;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

@RestController
@RequestMapping("/test")
public class TestController {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class);
	
	// 需要自己先把RestTemplate注册到IOC
	@Autowired
	private RestTemplate restTemplate;
	
	// 从配置文件中读取到后端key
	@Value("${recaptcha.server-key}")
	private String serverKey;
	
	// 请求地址
	private static final String SITEVE_RIFY = "https://www.recaptcha.net/recaptcha/api/siteverify";
	
	@PostMapping
	public Object test (HttpServletRequest request,
						@RequestParam("name") String name,
						@RequestParam("token") String token) {
		
		LOGGER.info("name={}, token={}", name, token);
		
		HttpHeaders httpHeaders = new HttpHeaders();
		httpHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
		httpHeaders.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);

		MultiValueMap<String, Object> requestBody = new LinkedMultiValueMap<>();
		requestBody.add("secret", this.serverKey);		// 服务端key
		requestBody.add("response", token);				// 客户端提交的token
		requestBody.add("remoteip", request.getRemoteAddr()); // 客户的ip地址,不是必须的参数。
		
		ResponseEntity<String> responseEntity = restTemplate.postForEntity(SITEVE_RIFY, new HttpEntity<>(requestBody, httpHeaders), String.class);

		JsonObject jsonObject = JsonParser.parseString(responseEntity.getBody()).getAsJsonObject();
		
		LOGGER.info("recaptcha response={}", jsonObject);
		
		
		// 是否执行成功
		if (!jsonObject.get("success").getAsBoolean()){
			// 在失败的情况下,获取到异常状态码
			JsonArray errorCodes = jsonObject.get("error-codes").getAsJsonArray();
			LOGGER.error("recaptcha error={}", errorCodes);
			return Collections.singletonMap("success", Boolean.FALSE); 
		}
		
		// 评分
		double score = jsonObject.get("score").getAsDouble();
		
		if (score < 0.5) {
			// 如果低于0.5分,服务不接受该请求
			return Collections.singletonMap("success", Boolean.FALSE); 
		}
		
		return Collections.singletonMap("success", Boolean.TRUE);
	}
}

一次执行日志

i.s.web.controller.TestController    : name=qwdqw, token=03AGdBq26J8YBZT6VuzU27VyuOk-KmKxN-UB6ETQ_MKOuDyea8upMmMBsX6H3TZ5NNK_VwgvJpxEJVppdmHNERK2d4Eo_w-YpxCi0TJmTyWJLRXD7279DScPOLxuRbj0nH_pTyYJw7OCf9o06gOeBQUqF7bCI_I4rakW4LvQSXd5d2jyFBdOf-FET6vqYzOYB93LyOsKcZdMci9YxIJ-9p8x_gm9YetFvyzQBt5il7iDHEqeLAd7HfLSh6UVOeDtHDncbkIgKWitHv4DuEO8_O8Pm7Fz6Sdc_GoAJgPeYAHkZs5vMvPqwv6H7hUKhh8RI-zCm3cYKe6nYK3Fc7Mc1Xr5bRnJqrSgrJkLBva4v2y-gSffm7E8GmtFgE9Kgr1iaualNUVzmYAiTx
i.s.web.controller.TestController    : recaptcha response={"success":true,"challenge_ts":"2020-08-05T13:50:45Z","hostname":"localhost","score":0.9,"action":"test"}

隐私条款图标

使用这个版本的验证码,会在屏幕的右下角显示一个小图标。毕竟用了人家的东西,建议保留。

你非要隐藏它,可以添加一个css。

.grecaptcha-badge { 
	display: none; 
} 
CSS 复制 全屏

最后

就是这么简单,为了通用。可以抽象出一个验证拦截器,再定义一个注解。通过注解描述接口最低允许的评分。在拦截器中获取到注解值,进行判断和校验。这样通用性和灵活性就提高了很多。


原文:https://springboot.io/t/topic/2365

标签:springboot,ReCaptcha,GoogleReCaptcha3,验证码,springframework,token,org,import,recap
From: https://www.cnblogs.com/wjsqqj/p/17641787.html

相关文章

  • springboot验证码-AJ-captcha
    准备资料:若依版本:ruoyi-vue3.8.2【点我去下载】aj-captcha版本:1.3.0【去下源码】参考:若依官方文档-集成aj-captcha开始若依vue版本的验证码用了数学运算,还得手工输入计算结果。看了官方文档,改成了目前比较流行的拖动滑块方式。1.引入MAVEN依赖若依官方引入的是1.2.7版......
  • springboot验证码-easy-captcha工具包
    说明Java图形验证码,支持gif、中文、算术等类型,可用于JavaWeb、JavaSE等项目pom引入 <dependency> <groupId>com.github.whvcse</groupId> <artifactId>easy-captcha</artifactId> <version>1.6.2</version> </dependency> 详解参数类使用easy-cap......
  • springboot验证码-kaptcha
    前言网上实现生成验证码的方式有很多,我这里只记录下使用kaptcha生成验证码的方式。实现思路1、整合kaptcha,创建kaptcha的工具类。2、编写接口,在接口中使用kaptcha工具类来生成验证码图片(验证码信息)并返回。3、登录时从session中获取验证码进行校验。4、测试获取验证码......
  • springboot验证码-Hutool-captcha
    前言在Web应用程序中,为了保护用户信息的安全性,验证码已经成为了一个非常普遍的安全措施,而Hutool-captcha是一款非常优秀的开源图形验证码工具,简单易用,提供了丰富的特性,可以帮助我们快速实现验证码功能。本文将介绍如何使用SpringBoot整合Mybatis-Plus和Hutool-captcha实现验证码......
  • springboot验证码-kaptcha谷歌验证码工具
    验证码,就是将一串随机产生的数字或符号,生成一幅图片,图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息。Maven依赖在开发验证码功能的时候,kaptcha谷歌验证码工具,依赖。<!--验证码--><dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artif......
  • springboot验证码-kaptcha,hutool-captcha
    前言在springboot的登陆页面中为了防止机器大规模注册,机器暴力破解数据密码等危害,需要验证随机生成的验证码。现提出两种简易方案生成验证码功能,一种采用springboot整合kaptcha第三方验证码生成工具的生成方案;另一种采用springboot整合第三方类库hutool生成验证码,验证成功跳转至s......
  • SpringBoot 启动流程追踪(第二篇)
    上一篇文章分析了除refresh方法外的流程,并着重分析了load方法,这篇文章就主要分析refresh方法,可以说refresh方法是springboot启动流程最重要的一环,没有之一。我们通常在分析源码的过程中,都需要带着一个目标去看,不然看这看那,感觉什么都没有看一样。这篇文章的目标在于弄懂......
  • Springboot使用Redisson作为分布式锁
    官方地址:https://github.com/redisson/redisson/wiki/Table-of-Content一些官网说明    Redisson采用了基于NIO的Netty框架,不仅能作为Redis底层驱动客户端,具备提供对Redis各种组态形式的连接功能,对Redis命令能以同步发送、异步形式发送、异步流形式发送或管道形式发送的功能......
  • Springboot中实现观察者模式
    在SpringBoot中实现观察者模式可以通过以下步骤进行:1.定义观察者接口(Observer):创建一个接口,定义观察者对象需要实现的方法,例如update()方法。publicinterfaceObserver{voidupdate();}2.实现具体的观察者(具体实现Observer接口的类):创建一个或多个具体的观察者类,实......
  • springboot redssion 单机模式/集群模式/哨兵模式连接
    引入依赖:<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.10.7</version></dependency><dependency><groupId>......