JAVA后端生成图片滑块验证码 springboot+js完整案例
前言
现在大部分网部都是图片滑块验证码,这个得要与后端联动起来才是确保接口安全性
通过我们系统在发送手机短息时都会选进行滑块验证,但是我们要保证发送短息接口的全安,具体路思如下
那么这个滑块的必须是与后端交互才能保证安全性,而不是前端简单的交互。我们一起来学习一下这个案例怎么实吧
1、验证通过效果如图
2、验证失败效果如图
案例开始
1、我们使用java新建一个springboot工程,并准备几张图片,尺寸是390*180,如下图
添加依赖
<dependency><groupId>net.coobird</groupId><artifactId>thumbnailator</artifactId><version>0.4.11</version>
</dependency>
2、新建三个响应的类
2.1 WebReturn类如下
@Data
public class WebReturn {RetCode code;Object data;public WebReturn(RetCode code, Object data) {this.code = code;this.data = data;}
}
2.2 RetCode类如下
public enum RetCode {IMAGE_REQ_SUCCESS(1,"图片请求成功"),IMAGE_REQ_FAIL(2,"图片请求失败"),VERIFI_REQ_SUCCESS(3,"图片验证成功"),VERIFI_REQ_FAIL(4,"图片验证失败");int code;String message;RetCode(int code, String message) {this.code = code;this.message = message;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}
2.3 ImageResult类如下
@Data
public class ImageResult {int xpos;//滑块的坐标x轴int ypos;//滑块的坐标y轴int cutImageWidth;//滑块的宽int cutImageHeight;//滑块的高String cutImage;//滑块图片String oriImage;//背景图(初扣掉滑块的图)}
3、新建一个图片滑块生成的工具类
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@Slf4j
public class ImgUtil {//图片的路径private String classpath = "classpath*:img/slider/*.*";//图片的最大大小 (可以根据实际需要进行高调整,对应的图片尺寸也得是一致)private static int IMAGE_MAX_WIDTH = 380;private static int IMAGE_MAX_HEIGHT = 190;//抠图上面的半径private static int RADIUS = IMAGE_MAX_WIDTH/38;//抠图区域的高度private static int CUT_HEIGHT = IMAGE_MAX_WIDTH/7;//抠图区域的宽度private static int CUT_WIDTH = IMAGE_MAX_WIDTH/7;//被扣地方填充的颜色private static int FLAG = 0xffffff;//抠图部分凸起的方向private Location location;ImageResult imageResult = new ImageResult();private String ORI_IMAGE_KEY = "ORI_IMAGE_KEY";private String CUT_IMAGE_KEY = "CUT_IMAGE_KEY";private int XPOS;private int YPOS;@Dataprivate class ImageMessage{private int xpos;private int ypos;private int cutImageWidth;private int cutImageHeight;}ImageMessage imageMessage = new ImageMessage();/***功能描述 获取抠图区的坐标原点*/public void createXYPos(BufferedImage oriImage){int height = oriImage.getHeight();int width = oriImage.getWidth();XPOS = new Random().nextInt(width-CUT_WIDTH-RADIUS);YPOS = new Random().nextInt(height-CUT_HEIGHT-RADIUS-RADIUS)+RADIUS;//确保横坐标位于2/4--3/4int div = (IMAGE_MAX_WIDTH/4);if(XPOS/div == 0 ){XPOS = XPOS + div*2;}else if(XPOS/div == 1 ){XPOS = XPOS + div;}else if(XPOS/div == 3 ){XPOS = XPOS - div;}}/***功能描述 对外提供的接口*/public ImageResult imageResult() throws IOException{return imageResult(getRandomImage());}public ImageResult imageResult(BufferedImage oriBufferedImage) throws IOException {//检测图片大小oriBufferedImage = checkImage(oriBufferedImage);//初始化原点坐标createXYPos(oriBufferedImage);//获取被扣图像的标志图int[][] blockData = getBlockData(oriBufferedImage);//printBlockData(blockData);//计算抠图区域的信息createImageMessage();//获取扣了图的原图和被扣部分的图Map<String,BufferedImage> imageMap = cutByTemplate(oriBufferedImage,blockData);imageResult.setOriImage(ImageBase64(imageMap.get(ORI_IMAGE_KEY)));imageResult.setCutImage(ImageBase64(imageMap.get(CUT_IMAGE_KEY)));imageResult.setXpos(imageMessage.getXpos());imageResult.setYpos(imageMessage.getYpos());imageResult.setCutImageWidth(imageMessage.getCutImageWidth());imageResult.setCutImageHeight(imageMessage.getCutImageHeight());return imageResult;}/***功能描述* @Description 计算抠图的相关参数*/private void createImageMessage(){int x = 0,y = 0;int w = 0, h = 0;if(location == Location.UP){x = XPOS;y = YPOS - RADIUS;w = CUT_WIDTH;h = CUT_HEIGHT + RADIUS;}else if(location == Location.LEFT){x = XPOS-RADIUS;y = YPOS;w = CUT_WIDTH + RADIUS;h = CUT_HEIGHT;}else if(location == Location.DOWN){x = XPOS;y = YPOS;w = CUT_WIDTH;h = CUT_HEIGHT + RADIUS;}else if(location == Location.RIGHT){x = XPOS;y = YPOS;w = CUT_WIDTH + RADIUS;h = CUT_HEIGHT;}imageMessage.setXpos(x);imageMessage.setYpos(y);imageMessage.setCutImageHeight(h);imageMessage.setCutImageWidth(w);}/***功能描述* @Description 检测图片大小是否符合要求*/private BufferedImage checkImage(BufferedImage image) throws IOException {if((image.getWidth() == IMAGE_MAX_WIDTH) || (image.getHeight() == IMAGE_MAX_HEIGHT)){return image;}else if((image.getWidth() < IMAGE_MAX_WIDTH) || (image.getHeight() < IMAGE_MAX_HEIGHT)){log.info("图片太小.不符合要求w*h[380*190]");throw new IllegalArgumentException("图片太小.不符合要求w*h[380*190]");} else {log.info("压缩图片");return compressImage(image,IMAGE_MAX_WIDTH,IMAGE_MAX_HEIGHT);}}private Color color(int rgb){int b = (0xff & rgb);int g = (0xff & (rgb >> 8));int r = (0xff & (rgb >> 16));return new Color(r, g, b);}/***功能描述 获取抠完图的原图和被扣出来的图*/public Map<String,BufferedImage> cutByTemplate(BufferedImage oriImage, int[][] blockData){Map<String,BufferedImage> imgMap = new HashMap<>();BufferedImage cutImage = new BufferedImage(imageMessage.cutImageWidth,imageMessage.cutImageHeight,oriImage.getType());// 获取Graphics2DGraphics2D g2d = cutImage.createGraphics();//透明化整张图cutImage = g2d.getDeviceConfiguration().createCompatibleImage(imageMessage.cutImageWidth,imageMessage.cutImageHeight, Transparency.BITMASK);g2d.dispose();g2d = cutImage.createGraphics();// 背景透明代码结束int xmax = imageMessage.xpos + imageMessage.cutImageWidth;int ymax = imageMessage.ypos + imageMessage.cutImageHeight;for(int x = imageMessage.xpos; x< xmax && x>=0; x++){for(int y = imageMessage.ypos; y < ymax && y>=0; y++){int oriRgb = oriImage.getRGB(x,y);if(blockData[x][y] == FLAG){oriImage.setRGB(x,y,FLAG);//描边 判断是否为边界,如果是边界则填充为白色if(blockData[x-1][y] != FLAG || blockData[x+1][y] != FLAG || blockData[x][y+1] != FLAG || blockData[x][y-1] != FLAG){g2d.setColor(color(0xffffff));}else{g2d.setColor(color(oriRgb));}g2d.setStroke(new BasicStroke(1f));g2d.fillRect(x-imageMessage.xpos, y-imageMessage.ypos, 1, 1);}}}// 释放对象g2d.dispose();imgMap.put(ORI_IMAGE_KEY,oriImage);imgMap.put(CUT_IMAGE_KEY,cutImage);return imgMap;}/***功能描述* @Description 获取抠图数据,被扣的像素点将使用FLAG进行标记* @return: int[][]*/public int[][] getBlockData(BufferedImage oriImage){int height = oriImage.getHeight();int width = oriImage.getWidth();int[][] blockData =new int[width][height];Location locations[] = {Location.UP,Location.LEFT,Location.DOWN,Location.RIGHT};//矩形//此处还可以优化,进行区域扫描for(int x = 0; x< width && x>=0; x++){for(int y = 0; y < height && y>=0; y++){blockData[x][y] = 0;if ( (x > XPOS) && (x < (XPOS+CUT_WIDTH))&& (y > YPOS) && (y < (YPOS+CUT_HEIGHT))){blockData[x][y] = FLAG;}}}//圆形突出区域//突出圆形的原点坐标(x,y)int xBulgeCenter=0,yBulgeCenter=0;int xConcaveCenter=0,yConcaveCenter=0;//位于矩形的哪一边,0123--上下左右location = locations[new Random().nextInt(4)];if(location == Location.UP){//上 凸起xBulgeCenter = XPOS + CUT_WIDTH/2;yBulgeCenter = YPOS;//左 凹陷xConcaveCenter = XPOS ;yConcaveCenter = YPOS + CUT_HEIGHT/2;}else if(location == Location.DOWN){//下 凸起xBulgeCenter = XPOS + CUT_WIDTH/2;yBulgeCenter = YPOS + CUT_HEIGHT;//右 凹陷xConcaveCenter = XPOS + CUT_WIDTH;yConcaveCenter = YPOS + CUT_HEIGHT/2;}else if(location == Location.LEFT){//左 凸起xBulgeCenter = XPOS ;yBulgeCenter = YPOS + CUT_HEIGHT/2;//下 凹陷xConcaveCenter = XPOS + CUT_WIDTH/2;yConcaveCenter = YPOS + CUT_HEIGHT;}else {//Location.RIGHT//右 凸起xBulgeCenter = XPOS + CUT_WIDTH;yBulgeCenter = YPOS + CUT_HEIGHT/2;//上 凹陷xConcaveCenter = XPOS + CUT_WIDTH/2;yConcaveCenter = YPOS;}//半径的平方int RADIUS_POW2 = RADIUS * RADIUS;//凸起部分for(int x = xBulgeCenter-RADIUS; x< xBulgeCenter+RADIUS && x>=0; x++){for(int y = yBulgeCenter-RADIUS; y < yBulgeCenter+RADIUS && y>=0; y++){if(Math.pow((x-xBulgeCenter),2) + Math.pow((y-yBulgeCenter),2) < RADIUS_POW2){blockData[x][y] = FLAG;}}}//凹陷部分for(int x = xConcaveCenter-RADIUS; x< xConcaveCenter+RADIUS && x>=0; x++){for(int y = yConcaveCenter-RADIUS; y < yConcaveCenter+RADIUS && y>=0; y++){if(Math.pow((x-xConcaveCenter),2) + Math.pow((y-yConcaveCenter),2) <= RADIUS_POW2){blockData[x][y] = 0;}}}return blockData;}/***功能描述 将图片转为base64存储*/private String ImageBase64(BufferedImage bufferedImage) throws IOException {ByteArrayOutputStream out = new ByteArrayOutputStream();ImageIO.write(bufferedImage, "png", out);//转成byte数组byte[] bytes = out.toByteArray();Base64.Encoder encoder = Base64.getEncoder();//生成BASE64编码return encoder.encodeToString(bytes);}/*** 随机获取一个图片文件* @return* @throws Exception*/private BufferedImage getRandomImage() throws IOException {try {//使用resource获取resource文件【注意:即使打成jar包也有效】ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();Resource[] resources = resourcePatternResolver.getResources(classpath);if (resources.length <= 0) {throw new IOException("该文件夹内没有文件!");} else {int index = new Random().nextInt(resources.length);InputStream inputStream = resources[index].getInputStream();BufferedImage marioBufferedImage = ImageIO.read(inputStream);return marioBufferedImage;}} catch (IOException e) {log.info("读取文件失败:{}", e);throw new IOException("读取文件失败!");}}/***功能描述 压缩图片* @author lgj* @Description* @date 3/30/20* @param:* @return: java.awt.image.BufferedImage**/private BufferedImage compressImage(BufferedImage image,int width,int height) throws IOException{return Thumbnails.of(image).forceSize(width,height)//.width(width).height(height).asBufferedImage();}/***功能描述* @Description 抠图部分凸起的区域*/private enum Location {UP,LEFT,DOWN,RIGHT;}
}
4、新建一个controller
@Slf4j
@RestController
@RequestMapping("/slider")
public class SliderController {private int xPosCache = 0;//生产环境请把这个值存入redis中@RequestMapping("/image")public WebReturn image(){ImageResult imageResult = null;try{imageResult = new ImgUtil().imageResult();//生成图片xPosCache = imageResult.getXpos();//生产环境请把这个值存入redis中imageResult.setXpos(0);//清空x值return new WebReturn(RetCode.IMAGE_REQ_SUCCESS,imageResult);}catch(Exception ex){log.error(ex.getMessage());ex.printStackTrace();return new WebReturn(RetCode.IMAGE_REQ_FAIL,null);}}@RequestMapping("/verification")public WebReturn verification(@RequestParam("moveX") int moveX){log.info("/slider/verification/{}",moveX);int MOVE_CHECK_ERROR = 2;//允许的误差范围,这里设置为2个像素//xPosCache 生产请从redis中读取,使用完并立即请除if(( moveX < ( xPosCache + MOVE_CHECK_ERROR)) && ( moveX > (xPosCache - MOVE_CHECK_ERROR))){log.info("验证正确");//生产这个可以返回临时授权码return new WebReturn(RetCode.VERIFI_REQ_SUCCESS,true);}return new WebReturn(RetCode.VERIFI_REQ_FAIL,false);}
}
5、最后新建一个页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>首页</title><script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script><style >html body {height: 100%;width: 100%;}#captchaContainer{position: absolute;top: 50px;left: 40%;/* background-color: #f57a7a;*/height: 275px;width: 260px;}.header{position: absolute;top: 0px;left: 0px;background-color: rgb(245, 236, 236);height: 40px;width: 380px;}.headerText{position: absolute;top: 13px;left: 140px;height: 40px;color:#66c523;font:18px/14px Georgia, "Times New Roman", Times, serif;}#captchaImg{position: absolute;left: 0;top: 40px;height: 190px;width: 380px;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;border: none}#oriImg{position: absolute;left: 0px;top: 0px;width: 380px;height: 190px;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;border: none}#cutImg{position: absolute;border: none;left: 0px;}.sliderContainer {position: absolute;bottom: 0;left: 0px;text-align: center;width: 380px;height: 40px;line-height: 40px;background: #f7f9fa;color: #45494c;border: 1px solid #e4e7eb;}.sliderContainer_success{border: 1px solid hsl(125, 93%, 44%);}.sliderContainer_fail{border: 1px solid #ec3655;}.slider {position: absolute;top: 0;left: 0px;width: 40px;height: 40px;background: #fff;box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);transition: background .2s linear;cursor: pointer;cursor: grab;}.slider_success{border: 1px solid hsl(125, 93%, 44%);}.slider_fail{border: 1px solid #ec3655;}.sliderContainer_active .slider {height: 38px;top: -1px;border: 1px solid #1991FA;}.sliderContainer_active .sliderMask {height: 38px;border-width: 1px;}.sliderContainer_success .slider {height: 38px;top: -1px;margin-left: -1px;border: 1px solid #52CCBA;background-color: #52CCBA !important;}.sliderContainer_success .sliderMask {height: 38px;border: 1px solid #52CCBA;background-color: #D2F4EF;}.sliderContainer_success .sliderIcon {background-position: 0 0 !important;}.sliderContainer_fail .slider {height: 38px;top: -1px;border: 1px solid #f57a7a;background-color: #f57a7a !important;}.sliderContainer_fail .sliderMask {height: 38px;border: 1px solid #f57a7a;background-color: #fce1e1;}.sliderContainer_fail .sliderIcon {top: 14px;background-position: 0 -82px !important;}.sliderContainer_active .sliderText, .sliderContainer_success .sliderText, .sliderContainer_fail .sliderText {display: none;}.sliderMask {position: absolute;left: 0;top: 0;height: 40px;border: 0 solid #1991FA;background: #D1E9FE;}.slider:active {cursor: grabbing;}.slider:hover {background: #1991FA;}.slider:hover .sliderIcon {background-position: 0 -13px;}.sliderIcon {position: absolute;top: 15px;left: 13px;width: 14px;height: 12px;background: url(http://cstaticdun.126.net//2.6.3/images/icon_light.f13cff3.png) 0 -26px;background-size: 34px 471px;}.refreshIcon {position: absolute;right: 0;top: 0;width: 34px;height: 34px;cursor: pointer;background: url(http://cstaticdun.126.net//2.6.3/images/icon_light.f13cff3.png) 0 -437px;background-size: 34px 471px;}</style></head>
<body><div id="captchaContainer"><!-- 标题栏 --><div class="header"><span class="headerText">图片滑动验证</span><span class="refreshIcon"/></div> <!-- 图片显示区域 --><div id="captchaImg"><img id="oriImg" src="dd" alt="原图"/><img id="cutImg" src="sa" alt="抠图"/></div><!--滑块显示区域--><div class="sliderContainer"><div class="sliderMask"><div class="slider"><span class="sliderIcon"></span></div></div><span class="sliderText">向右滑动填充拼图</span></div> </div></body><script>//图片显示使用base64时的前缀,src=base64PrefixPath + imgBase64Valuevar base64PrefixPath="data:image/png;base64,";var IMAGE_WIDTH = 380;//初始化//滑块初始偏移量var sliderInitOffset = 0;//滑块移动的最值var MIN_MOVE = 0;var MAX_MOVE = 0;//鼠标按下标志var mousedownFlag=false;//滑块移动的距离var moveX;//滑块位置检测允许的误差,正负2var MOVE_CHECK_ERROR = 2;//滑块滑动使能var moveEnable = true;var ImageMsg = {//抠图的坐标xpos: 0,ypos: 0,//抠图的大小cutImageWidth: 0,cutImageHeight: 0,//原图的base64oriImageSrc: 0,//抠图的base64cutImageSrc: 0,}//加载页面时进行初始化function init(){console.log("init")moveEnable = true;mousedownFlag=false;$(".slider").css("left",0+"px");initClass();MAX_MOVE = IMAGE_WIDTH - ImageMsg.cutImageWidth;console.log("ImageMsg = " + ImageMsg)$("#cutImg").css("left",0+"px");$("#oriImg").attr("src",ImageMsg.oriImageSrc)$("#cutImg").attr("src",ImageMsg.cutImageSrc)$("#cutImg").css("width",ImageMsg.cutImageWidth)$("#cutImg").css("height",ImageMsg.cutImageHeight)$("#cutImg").css("top",ImageMsg.ypos)}//加载页面时$(function(){httpRequest.requestImage.request();})var httpRequest={//请求获取图片requestImage:{path: "slider/image",request:function(){$.get(httpRequest.requestImage.path,function(data,status){console.log(data)console.log(data.message);if(data.data != null){ImageMsg.oriImageSrc = base64PrefixPath + data.data.oriImage;ImageMsg.cutImageSrc = base64PrefixPath + data.data.cutImage;ImageMsg.xpos = data.data.xpos;ImageMsg.ypos = data.data.ypos;ImageMsg.cutImageWidth = data.data.cutImageWidth;ImageMsg.cutImageHeight = data.data.cutImageHeight;init();}});},},//请求验证requestVerification:{path: "slider/verification",request:function(){$.get(httpRequest.requestVerification.path,{moveX:(moveX)},function(data,status){console.log(data)console.log(data.code);console.log(data.message);if(data.data == true){checkSuccessHandle();}else{checkFailHandle();}});},},}//刷新图片操作$(".refreshIcon").on("click",function(){httpRequest.requestImage.request();})//滑块鼠标按下$(".slider").mousedown(function(event){console.log("鼠标按下mousedown:"+event.clientX + " " + event.clientY);sliderInitOffset = event.clientX; mousedownFlag = true;//滑块绑定鼠标滑动事件$(".slider").on("mousemove",function(event){if(mousedownFlag == false){return;}if(moveEnable == false){return}moveX = event.clientX - sliderInitOffset;moveX<MIN_MOVE?moveX=MIN_MOVE:moveX=moveX;moveX>MAX_MOVE?moveX=MAX_MOVE:moveX=moveX;$(this).css("left",moveX+"px");$("#cutImg").css("left",moveX+"px");})})//滑块鼠标弹起操作$(".slider").mouseup(function(event){console.log("mouseup:"+event.clientX + " " + event.clientY);sliderInitOffset = 0;$(this).off("mousemove");mousedownFlag=false;console.log("moveX = " + moveX)checkLocation();})//检测滑块 位置是否正确function checkLocation(){moveEnable = false;//后端请求检测滑块位置httpRequest.requestVerification.request();}function checkSuccessHandle(){$(".sliderContainer").addClass("sliderContainer_success");$(".slider").addClass("slider_success");}function checkFailHandle(){$(".sliderContainer").addClass("sliderContainer_fail");$(".slider").addClass("slider_success");}function initClass(){$(".sliderContainer").removeClass("sliderContainer_success");$(".slider").removeClass("slider_success");$(".sliderContainer").removeClass("sliderContainer_fail");$(".slider").removeClass("slider_fail");}</script></html>
最后
到这里我们的案例代码已经写好了,运程工程访问就可以了。
http://localhost:9005/home.html
本文章提供大家学习,欢迎你大家留言提供您的保贵意见
=如果本文对您有帮助,麻烦您给博主点个赞吧!=
相关文章:

JAVA后端生成图片滑块验证码 springboot+js完整案例
前言 现在大部分网部都是图片滑块验证码,这个得要与后端联动起来才是确保接口安全性 通过我们系统在发送手机短息时都会选进行滑块验证,但是我们要保证发送短息接口的全安,具体路思如下 那么这个滑块的必须是与后端交互才能保证安全性&…...

Spring Boot中的自动装配机制
文章目录 1. 什么是自动装配?2. 自动装配是如何工作的?3. 如何开启自动装配?4. 自动装配的注意事项5. 结语推荐阅读文章 在Spring Boot的世界里,自动装配(Auto-configuration)就像春风拂面,轻轻…...

Brave127编译指南 Windows篇:配置Git(四)
1. 概述 在Brave浏览器的开发过程中,Git作为核心版本控制工具扮演着不可或缺的角色。作为当今最广泛使用的分布式版本控制系统,Git为开发者提供了强大的源码管理能力。通过Git,您可以轻松追踪代码变更、管理不同版本,并与其他开发…...

mysql数据库(五)多表查询
多表查询 文章目录 多表查询一、链表查询1.1交叉连接1.2 内连接1.3 左连接1.4 右连接1.5 全连接1.6 例子 二、子查询2.1 in与not in2.2 any/some2.3 all2.4 比较运算符2.5 exists 三、例子 查询中使用的表如下所示 ------------ | id | name | ------------ | 1 | IT | …...

【go从零单排】JSON序列化和反序列化
🌈Don’t worry , just coding! 内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。 📗概念 在 Go 语言中,处理 JSON 数据主要依赖于 encoding/json 包。这个包提…...

海外携程机票token 1001分析
声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 有相关问题请第一时间头像私信联系我删…...

【算法】——二分查找合集
阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 零:二分查找工具 1:最基础模版 2:mid落点问题 一:最…...

社会工程骗局席卷金融机构
2024 年北美金融机构收到的社交工程诈骗报告数量比一年前增加了 10 倍。数据显示,诈骗现在占所有数字银行欺诈的 23%。 深度伪造和 GenAI 诈骗的危险日益增加 BioCatch 在其 2024 年北美数字银行欺诈趋势报告中公布了这些发现,该报告还详细说明了报告的…...

前缀和算法习题篇(上)
1.一维前缀和 题目描述: 解法一:暴力解法:模拟 时间复杂度是O(n*q),会超时。 解法二:前缀和解法:快速求出数组中某一个连续区间的和 快速是指O(1),前缀和思想可把时间复杂度可降到O(q)。 算法思路: 先预处…...

C#核心(9)静态类和静态构造函数
前言 我们先前已经了解了静态成员的基本构成,也简单了解了一下静态变量,现在我们就要来看一下静态类和静态构造函数了,这些其实在上一节我已经在例子里有提到过,相信聪明的你甚至已经发现了一些规律。 GPT对c#中静态类和静态构造…...

B2002 Hello,World! C++实现
Hello,World! 题目描述 编写一个能够输出 Hello,World! 的程序。 提示: 使用英文标点符号;Hello,World! 逗号后面没有空格。H 和 W 为大写字母。 输入格式 输出格式 样例 #1 样例输入 #1 无样例输出 #1 Hello,World!#include <bits/stdc.h&…...

前端-同源与跨域
一、同源策略 两个网站协议名、域名、端口号有一个不同就是非同源,就是跨域。跨域问题就是浏览器的同源策略造成的。 同源是指协议名、域名、端口号 必须完全一致! http 默认端口号是80,https 默认端口号是443 同源策略的限制 一般来说&…...

MySQL远程连接错误解决:Host is not allowed to connect to this MySQL server
1. 异常错误 通过远程客户端访问MySQL服务器时会遇到“Host is not allowed to connect to this MySQL server”的错误提示。 2. 原因 MySQL服务器当前配置不允许来自特定主机的连接尝试。 3. 解决方法 允许远程主机访问MySQL服务器,按照以下步骤操作ÿ…...

详解C语言字符和字符串的输入与输出
字符和字符串的输入与输出 一、字符的输入与输出1.1 字符的输入使用 getchar()使用 scanf() 1.2 字符的输出使用 putchar()使用 printf() 二、字符串的输入与输出2.1 字符串的输入使用 scanf() 输入字符串使用 fgets() 输入字符串 2.2 字符串的输出使用 printf() 输出字符串使用…...

adworld - stack2
adworld - stack2 题目概述:给一个数组(自己控制数组大小和填入的数据),并进行(展示, 增加, 修改值, 求平均值, 退出)菜单选项 存在后门函数(system(“/bin/bash”)),但是没找到栈溢出的点 没判断数组的边界造成任意地址修改 但是如何准确…...

Python学习从0到1 day28 Python 高阶技巧 ⑤ 多线程
若事与愿违,请相信,上天自有安排,允许一切如其所是 —— 24.11.12 一、进程、线程 现代操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统。 进程 进程:就…...

nuget 管理全局包、缓存和临时文件夹
查看文件夹位置 dotnet nuget locals all --list清空数据 # Clear the 3.x cache (use either command) dotnet nuget locals http-cache --clear nuget locals http-cache -clear# Clear the 2.x cache (NuGet CLI 3.5 and earlier only) nuget locals packages-cache -clea…...

linux物理内存管理:node,zone,page
一、总览 对于物理内存内存,linux对内存的组织逻辑从上到下依次是:node,zone,page,这些page是根据buddy分配算法组织的,看下面两张图: 上面的概念做下简单的介绍: Node:…...

uniapp 设置安全区域
<!-- 获取安全区域 --> <script setup lang"ts"> import { computed, ref } from vuelet systemType ref(1) // #ifdef APP-PLUS || H5 || APP-PLUS-NVUE systemType.value 1 const { safeAreaInsets } uni.getSystemInfoSync() console.log(safeAre…...

渐进式JavaScript框架Vue 3 入门
目录 前言1. Vue 3 的基础入门1.1 什么是 Vue.js1.2 局部使用 Vue 2. Vue 3 的基本配置2.1 准备 HTML 页面并引入 Vue 模块2.2 创建 Vue 应用实例 3. Vue 的数据绑定与界面渲染3.1 插值表达式 4. 常用指令详解4.1 v-for 指令:列表渲染4.2 v-bind 指令:绑…...

【真题笔记】21年系统架构设计师案例理论点总结
【真题笔记】21年系统架构设计师案例理论点总结 从机器学习定义的灵活性和学习算法的可扩展性,对解释器+管道过滤器+隐式调用进行对比分析!面向对象方法开发软件,建立对象模型+动态模型+功能模型,三者关联关系!数据架构的设计过程包括:数据定义、数据分布、数据管理,三者…...

PostgreSQL的奥秘:深入探究事务与锁的秘密世界
PostgreSQL事务 1. 概述 在数据库系统中,事务(Transaction)是执行数据库操作的最小逻辑单位。它确保了一组操作的完整性和一致性。事务可以通过显式的 BEGIN、COMMIT 和 ROLLBACK 语句块来控制,也可以在自动提交模式(…...

Python进行GRPC和Dubbo协议的高级测试
在微服务架构日益流行的今天,分布式系统的复杂性不断增加。GRPC 和 Dubbo 协议作为当今互联网行业中常见的高性能通信协议,已经成为服务之间交互的核心。然而,随着服务调用层次的不断增加,如何有效地测试这两种协议,确…...

全程云OA系统QCPES.asmx存在SQL注入漏洞
免责声明: 本文旨在提供有关特定漏洞的深入信息,帮助用户充分了解潜在的安全风险。发布此信息的目的在于提升网络安全意识和推动技术进步,未经授权访问系统、网络或应用程序,可能会导致法律责任或严重后果。因此,作者不对读者基于本文内容所采取的任何行为承担责任。读者在…...

从建立TRUST到实现FAIR:可持续海洋经济的数据管理
1. 引言 随着我们对信息管理方式的信任,我们的社会对数字化数据的以来呈指数级增长。为了跟上大数据的需求,通过不断的努力和持续实践,对“good”数据管理方式的共识也在不断发展和演变。 加拿大正在建设国家基础设施和服务以及研究数据管理…...

基于SSM的“汽车销售分析与管理系统”的设计与实现(源码+数据库+文档+PPT)
基于SSM的“汽车销售分析与管理系统”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SSM 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统功能结构图 销售经理系统首页图 客户管理图 车辆销…...

vs2015QT项目添加多语言翻译总结
一、简介 当软件有国际化的需求时,就需要多语言翻译功能,最常见的语言就是支持中文和英语,本文介绍在vs2015QT环境下,进行国际化翻译的具体流程。 二、多语言翻译实现流程 1.底层实现原理介绍 QT写的客户端软件,能…...

替换OpenTSDB和HBase,宝武集团使用IoTDB助力钢铁设备智能运维
时序数据库 IoTDB 应用于宝武集团全基地钢铁时序数据管理,激活数据资产,赋能大型设备智能运维。 1. 背景概述 宝武装备智能科技有限公司(以下简称:宝武智维)是中国宝武设备智能运维专业化平台公司,30 余年始…...

MathGPT的原理介绍,在中小学数学教学的应用场景,以及代码样例实现
大家好,我是微学AI,今天给大家介绍一下MathGPT的原理介绍,在中小学数学教学的应用场景,以及代码样例实现。MathGPT的核心架构是一个精心设计的多层次系统,旨在有效处理复杂的数学问题。其主要组成部分包括 数学知识图谱…...

前端框架大比拼:React.js, Vue.js 及 Angular 的优势与适用场景探讨
文章目录 前言一、React.js特点使用方法适用场景 二、Vue.js特点使用方法适用场景 三、Angular特点使用方法适用场景 四、如何选择合适的前端框架五、前端框架对项目性能的影响结语 前言 随着互联网技术的飞速发展,前端开发已经从简单的页面展示演变为复杂的应用构…...