基于 Kaptcha 验证码检验的登录就该这么实现

验证码案例 —— Kaptcha 插件介绍 后端生成验证码,前端展示并进行session验证(带完整前后端源码) 正常来说, 127.0.0.1:8080/index.html 和 localhost:8080/index.html 都可以,但是博主自己验证包括找了些其他博主验证,localhost:8080/index.html 访问的话是存在些许bug的,后端取session可能为空,原因是session没有设置。随着安全性的要求越来越⾼, ⽬前项⽬中很多都使⽤了验证码, 验证码的形式也是多种多样, 更复杂的图形验证码和行为验证码已经成为了更流⾏的趋势. 阅读详情

在网站实际应用过程中,为了防止网站登录接口被机器人轻易地使用,产生一些没有意义的用户数据,所以,采用验证码进行一定程度上的拦截,当然,我们采用的还是一个数字与字母结合的图片验证码形式,后续会讲到更加复杂的数字计算类型的图片验证码,请持续关注我的博客。

实现思路

博主环境:springboot3 、java17、thymeleaf

  1. 访问登录页面

  2. 登录

    • 验证验证码
    • 验证账号、密码
    • 验证成功时,生成登录凭证,发放给客户端
    • 验证失败时,跳转回登录信息,并保留原有填入信息
  3. 退出

    • 将登录凭证修改为失效状态
    • 跳转至首页

访问登录页面的方法已经在前文说明过了,就不多加赘述了,展示一下代码:

// 登录页面
@RequestMapping(path = "/login", method = RequestMethod.GET)
public String getLoginPage() {
    return "/site/login";
}

访问完登录页面,我们就要进行信息输入,然而,现在,还没有把验证码信息正确展现出来,所以,接下来,我们先来实现验证码的部分。

所需两个数据表 SQL 代码如下:

注:注册流程可看前文。一文教你学会实现以邮件激活的注册账户代码_yumuing的博客-优快云博客

-- user表
DROP TABLE IF EXISTS `user`;
 SET character_set_client = utf8mb4 ;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) DEFAULT NULL,
  `password` varchar(50) DEFAULT NULL,
  `salt` varchar(50) DEFAULT NULL,
  `email` varchar(100) DEFAULT NULL,
  `type` int(11) DEFAULT NULL COMMENT '0-普通用户; 1-超级管理员; 2-版主;',
  `status` int(11) DEFAULT NULL COMMENT '0-未激活; 1-已激活;',
  `activation_code` varchar(100) DEFAULT NULL,
  `header_url` varchar(200) DEFAULT NULL,
  `create_time` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_username` (`username`(20)),
  KEY `index_email` (`email`(20))
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8;

-- 登录凭证表
DROP TABLE IF EXISTS `login_ticket`;
 SET character_set_client = utf8mb4 ;
CREATE TABLE `login_ticket` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `ticket` varchar(45) NOT NULL,
  `status` int(11) DEFAULT '0' COMMENT '1-有效; 0-无效;',
  `expired` timestamp NOT NULL,
  PRIMARY KEY (`id`),
  KEY `index_ticket` (`ticket`(20))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Kaptcha 验证码设计和校验

目前使用图片验证码较为广泛的是 Kaptcha ,它只有一个版本:2.3.2,值得注意的是,在 springboot 3的环境下,使用该插件包大部分会使用到的 http 包,不能导入 javax 包内的,而是应该导入jakarta 包内的。

它能够实现以下效果:水纹有干扰、鱼眼无干扰、水纹无干扰、阴影无干扰、阴影有干扰

验证码样式

其中,它们的文字内容限制、背景图片、文字颜色、大小、干扰样式颜色、整体(图片)高度、宽度、图片渲染效果、干扰与否都是可以进行自定义的。我们只要按需配置好对应的 configuration 即可。当然,它并没有默认集成进 springboot 中,使用之前必须先导入对应依赖,如下:

<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>

导包成功之后,我们就需要进行按需设置配置类了,它相关配置属性如下:

配置类属性信息

配置类模板如下:

package top.yumuing.community.config;

import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration
public class KaptchaConfig {

    @Bean
    public Producer kaptchaProduce(){
        Properties properties=new Properties();
        //图片的宽度
        properties.setProperty("kaptcha.image.width","100");
        //图片的高度
        properties.setProperty("kaptcha.image.height","40");
        //字体大小
        properties.setProperty("kaptcha.textproducer.font.size","32");
        //字体颜色(RGB)
        properties.setProperty("kaptcha.textproducer.font.color","0,0,0");
        //验证码字符的集合
        properties.setProperty("kaptcha.textproducer.char.string","123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        //验证码长度(即在上面集合中随机选取几位作为验证码)
        properties.setProperty("kaptcha.textproducer.char.length","4");
        //图片的干扰样式:默认存在无规则划线干扰
        //无干扰:com.google.code.kaptcha.impl.NoNoise
		properties.setProperty("kaptcha.noise.impl","com.google.code.kaptcha.impl.NoNoise");
        //图片干扰颜色:默认为黑色
        properties.setProperty("kaptcha.noise.color", "black");
        //图片渲染效果:默认水纹
        // 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
        //properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");

        DefaultKaptcha Kaptcha = new DefaultKaptcha();
        Config config=new Config(properties);
        Kaptcha.setConfig(config);
        return Kaptcha;
    }
}

配置好相关属性之后,我们就可以进行验证码生成的接口开发了,首先,让 Producer 进入 Bean 工厂进行管理,之后,再生成验证码文本并传入 session 中,以便后续进行验证码校验,之后,再生成对应验证码图片,以 BufferedImage 的形式存储,并利用 HttpServletResponse 和 ImageIO 将图片传输给浏览器,其中,注意设置好图片返回类型,并且无需手动关闭 IO 流,springboot 会进行管理,实现自行关闭。此时以 Get 方法访问 域名/imageCode ,就会返回对应验证码图片了。

//验证码
@RequestMapping(path = "/imageCode",method = RequestMethod.GET)
public void getImgCode(HttpServletResponse response, HttpSession session){
    String codeText = imageCodeProducer.createText();
    BufferedImage imageCode = imageCodeProducer.createImage(codeText);

    // 将验证码文本存入 session
    session.setAttribute("imageCode", codeText);

    //设置返回类型
    response.setContentType("image/jpg");

    try {
        OutputStream os = response.getOutputStream();
        ImageIO.write(imageCode, "jpg", os);
    } catch (IOException e) {
        logger.error("响应验证码失败!"+e.getMessage());
    }
    
}

当然,有些浏览器为了节省用户访问流量,较为智能地将已获取的静态资源链接自动不再访问,所以,需要添加额外参数完成浏览器适配,这里采用的是利用 JavaScript 把每次访问验证码图片的链接添加一个随机数字的参数,以保证智能节省流量的问题。当然,我们不用去 controller 获取该参数,因为没有意义,也不要求一定要所有参数都匹配到。代码如下:

function refresh_imageCode() {
    var path = "/imageCode?p=" + Math.random();
    $("#imageCode").attr("src", path);
}

获取到验证码,我们就必须对其进行校对,只有验证码通过之后,才能去校验账户和密码。而验证码校对最重要的一点就是,需要忽略大小写,不能苛求用户的耐心。校验验证码不通过的情况不仅仅需要考虑发送方的验证码文本为空或者文本不一致导致的错误,还需要考虑接受方(服务端)的验证码文本究竟有没有存储下来,以防通过接口工具直接 post 访问该接口产生的空数据。代码如下:

//登录
@RequestMapping(path = "/login",method = RequestMethod.POST)
public String login(String username, String password, String code,
                    boolean rememberMe, Model model, HttpSession session, HttpServletResponse response){
    String imageCode = (String) session.getAttribute("imageCode");
    // 验证码
    if (StringUtils.isBlank(imageCode) || StringUtils.isBlank(code) || !imageCode.equalsIgnoreCase(code)){
        model.addAttribute("codeMsg","验证码不正确!");
        return "/site/login";
    }
}

记住我功能的实现

用户进行登录时,常常需要勾选是否记住的按钮,这是为了保证用户长时间使用该应用而不因为需要频繁登录,丧失用户量。当然,也有部分用户不希望自己的用户凭证长时间保存,希望通过经常性更新,保证一定程度上的用户数据安全。实现这个功能并不困难,只要发送数据时,多添加一个布尔参数而已。为了便于代码阅读,增加两个常量:登录默认状态超时时间常量、记住我登录状态超时时间常量,如下:

// 默认登录状态超时常量
int DEFAULT_EXPIRED_SECONDS = 3600 * 12;

// 记住状态的登录凭证超时时间
int REMEMBER_EXPIRED_SECONDS = 3600 * 24 * 100;

之后在登录接口进行判断就行,记住我布尔值为 true ,故代码如下:

// 是否记住我
int expiredSeconds = rememberMe ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS;

校验账号和密码

按照标准流程,先从数据访问层开始写,我们校验账户和密码都是使用查询语句就行了,当然,一句查询语句就行,不用为了两个参数就建两个查询语句,因为我们已经获得了这个对象,直接使用映射方法里的 get 方法就行,再进行所需要的校验工作。这里采用的是 username 为参数的查询语句来获取 user 对象。具体代码如下:

userMapper.java

User selectOneByUsername(@Param("username") String username);

userMapper.xml

<sql id="Base_Column_List">
    id,username,password,
    salt,email,type,
    status,activation_code,header_url,
    create_time
</sql>
<select id="selectOneByUsername" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from user
    where
    username = #{username,jdbcType=VARCHAR}
</select>

使用该查询语句之前,我们必须先保证传过来的账户和密码不能为空,查询才有意义,获取到 user 对象之后,我们先验证账户存不存在,如果不存在,返回错误信息就行了,如果存在的话,检查它的账户状态是否是激活状态,不是的话,返回错误信息,是的话,我们就能进行校验工作了,当然,账户存在,用户名就不用校验了,只需要校验密码就行了。代码如下:

//空值处理
if(StringUtils.isBlank(username)){
    map.put("usernameMsg", "账号不能为空!");
    return map;
}
if (StringUtils.isBlank(password)){
    map.put("passwordMsg", "密码不能为空!");
    return map;
}

//验证账号
User user = userMapper.selectOneByUsername(username);
if (user == null){
    map.put("usernameMsg","该账号不存在");
    return map;
}

//验证状态
if (user.getStatus() == 0){
    map.put("usernameMsg","该账号未激活!");
    return map;
}


//验证密码
password = CommunityUtil.md5(password+user.getSalt());
if(!user.getPassword().equals(password)){
    map.put("passwordMsg","密码不正确!");
    return map;
}

当账户密码校验成功时,将登录凭证存入 cookie 即可,设置好全局可用,以及失效时间,只要设置好登录凭证失效时间,后续客户端会自动在时间到达,将登录凭证注销掉,以便我们把登录状态取消掉。如果校验不成功的话,就直接返回校验信息。在登录接口进行调用即可

// 检测账号密码
Map<String,Object> map = userServiceImpl.login(username,password,expiredSeconds);
if (map.containsKey("loginTicket")){
    //设置cookie
    Cookie cookie = new Cookie("loginTicket",map.get("loginTicket").toString());
    cookie.setPath("/");
    cookie.setMaxAge(expiredSeconds);
    response.addCookie(cookie);
    return "redirect:/index";
}else {
    model.addAttribute("usernameMsg",map.get("usernameMsg"));
    model.addAttribute("passwordMsg",map.get("passwordMsg"));
    return "/site/login";
}

生成登录凭证

还是先从数据访问层说起,注意生成自增id即可。具体的 xml 语句如下:

<insert id="insertAll" parameterType="LoginTicket" keyProperty="id">
    insert into login_ticket
    (id, user_id, ticket,
     status, expired)
    values (#{id,jdbcType=NUMERIC}, #{userId,jdbcType=NUMERIC}, #{ticket,jdbcType=VARCHAR},
            #{status,jdbcType=NUMERIC}, #{expired,jdbcType=TIMESTAMP})
</insert>

采用的是字母和数字混合的随机字符串的形式,利用的是 java.util.UUID 来生成的。将需要的参数利用 set 方法存入对象里面,再利用对应插入语句插入数据库即可,注意默认生效状态为 1。具体生成登录凭证的登录接口代码如下:

//生成登录凭证
LoginTicket loginTicket = new LoginTicket();
loginTicket.setUserId(user.getId());
loginTicket.setTicket(CommunityUtil.generateUUID());
loginTicket.setStatus(1);
loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000));
loginTicketMapper.insertAll(loginTicket);
map.put("loginTicket",loginTicket.getTicket());
return map;

不知道你们有没有察觉一个问题:失效时间到了,状态仍为生效状态的。我们的登录凭证生效状态是后续登录信息展示的关键,后续还会考虑,时间过期之后,生效状态该怎么去自动修改?或者不作修改该怎么去解决失效时间到了,状态仍为生效状态的问题,请持续关注博主,后续为你们解答。

将登录凭证发送给客户端,就基本完成了登录的实现。

求关注点赞
相关代码资源已上传,可看:项目代码

相关 bug

No primary or single unique constructor found for interface javax.servlet.http.HttpServletResponse

springboot3 下导不了 javax.servlet.http 包,必须导 jakarta.servlet.http

也就是 http 包 又更改了。

import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

不能导,不然会发生错误。

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
手把手教你基于 Kaptcha 验证码检验的登录 在网站实际应用过程中,为了防止网站登录接口被机器人轻易地使用,产生一些没有意义的用户数据,所以,采用验证码进行一定程度上的拦截,当然,我们采用的还是一个数字与字母结合的图片验证码形式。 阅读详情

相关推荐

正则表达式在验证码与数据校验中的实战应用与性能优化

正则表达式是一种用于描述字符串匹配模式的强大工具,其核心原理是通过定义特定规则来高效地搜索、匹配和验证文本。在软件工程实践中,正则表达式因其声明式的语法和卓越的性能,成为数据格式校验、文本解析和规则验证的首选技术。其技术价值在于能够以简洁、可维护的方式替代冗长的过程式逻辑,显著提升代码的健壮性和开发效率。在常见的应用场景中,如用户注册、登录和支付流程,正则表达式与验证码技术紧密结合,构成了系统安全与数据完整性的双重防线。本文聚焦于如何利用正则表达式精准处理验证码生成、校验及用户输入验证的全流程,通过解析手机

weixin_34211761的博客 402

Kaptcha 使用教程

Kaptcha 使用教程

weixin_57467236的博客 8153

【项目实战】基于API服务网关SpringCloud Gateway的webflux与Google的kaptcha实现图形验证码功能

基于SpringCloud 微服务架构的项目中,需要使用图形验证码,以下是使用的记录。

奶爸的编程之路,也就一周冷个三天 1557

Kaptcha(验证码)的认识与应用

Java 初学者的验证码生成工具

weixin_56703682的博客 4041

kaptcha-2.3.2.jar

谷歌 kaptcha 图片验证码

Vivado2022.2下载安装

链接:https://pan.baidu.com/s/1lyfE2d-VmaWC-_aR8ratCQ提取码:mt09。

weixin_61081689的博客 2万+

手把手教你验证码检验的登录

在网站实际应用过程中,为了防止网站登录接口被机器人轻易地使用,产生一些没有意义的用户数据,所以,采用验证码进行一定程度上的拦截,当然,我们采用的还是一个数字与字母结合的图片验证码形式,后续会讲到更加复杂的数字计算类型的图片验证码,请持续关注我的博客。

BASK2312的博客 1489

芯片设计中的setup和hold检查:为什么你的电路会跑飞?

本文深入解析了芯片设计中Setup与Hold检查的核心原理,它们是确保电路可靠运行的“黄金窗口”。通过剖析触发器物理本质、时序路径公式及检查方法,解释了Setup违例(数据太慢)和Hold违例(数据太快)如何导致电路“跑飞”,并提供了从RTL优化到物理实现的实战修复策略与协同优化技巧。

weixin_29268267的博客 477

Kaptcha验证码实现

Kaptcha验证码实现

爱敲键盘的程序源的博客 726

固定资产报废的损失鉴定怎么做?

在社会生产的日常中,企业经常会遇到固定资产报废的损失鉴定,那么怎么去做鉴定?哪些情况下能申请固定资产报废损失鉴定呢? 今天,华碧鉴定就和大家说一说固定资产报废损失鉴定那些事儿。 符合下列条件之一的固定资产可申请报废: 1、使用年限过长,功能丧失,完全失去使用价值,或不能使用并无修复价值的; 2、产品技术落后,质量差,耗能高,效率低,已属淘汰且不适于继续使用,或技术指标已达不到使用要求的; 3、严重损坏,无法修复的或虽能修复,但累计修理费已接近或超过市场价值的; 4、主要附件损坏,无.

weixin_50362670的博客 2117

ESP32IDF 通过 PCA9685控制舵机的程序bug处理

esp32 PCA9685 bug 舵机

ztvzbj的博客 726

Shiro 结合 kcaptcha实现登录验证

Kcaptcha结合Shiro实现登录验证

cloud的技术积累 2738

告别云端依赖:手把手教你在Windows 10/11上离线部署WhisperDesktop(含模型下载避坑指南)

本文详细介绍了如何在Windows 10/11上离线部署WhisperDesktop,包括硬件要求、模型下载、环境配置和实战应用。通过本地部署,用户可以实现高效的语音转文字功能,无需依赖云端服务,特别适合注重数据隐私和需要离线工作的场景。

weixin_33736048的博客 322

用java实现验证码(CAPTCHA)

一、关于验证码 首先来说,验证码在我们的日常登录,发表言论时比较常见,它是一种用来区分登录用户是人还是机器的一种公共自动程序。它可以防止恶意破解密码、刷票、论坛灌水。 二、用java来实现验证码 了解了验证码的作用,接下来我们就用java来实现验证码这一功能。首先我们先分析一下,怎么生成一个验证码。我们需要一个BufferedImage对象来保存图片;通过它来...

weixin_33830216的博客 797

【光子 AI 】LangGraph:Graph = 有向有环图 + 状态机实现原理详解:数据结构模型与核心算法代码实现逻辑解析

LangGraph核心原理解析:基于Pregel模型的消息传递图,结合有向有环图和状态机特性。关键实现包括:1) 共享状态机制(TypedDict/Pydantic模型)配合Reducer逻辑实现状态更新;2) 图拓扑结构通过邻接表维护节点和条件边;3) 检查点机制支持状态持久化和恢复。运行时采用Pregel循环算法,通过超级步迭代执行节点函数、应用状态归约、条件路由下一批节点,同时支持人工中断和异步并行处理。该架构使LangGraph具备循环执行、条件跳转等DAG无法实现的动态流程控制能力。

AI天才研究院 1036

【银河麒麟V10】【桌面】【服务器】系统启动问题

1、如果之前运行好好的,重启后系统报错,一般80%是因为fstab的问题,回想下之前有没有添加过外接存储,修改过/etc/fstab,如果是的话一般是因为存储异常(比如网络存储无法连接,本地存储路径变化)导致系统开机自检失败,导致无法正常启动; 处理方式:进入单用户(单用户进入的几种方式上面有专门文章介绍),修改/etc/fstab,将新增的内容暂时注释掉,然后重启系统,能正常进入系统后再分析失败原因。 ...

桂安俊@KylinOS 3万+

验证码的实现以及校验

1.使用谷歌提供的jar包,来自动生成验证码,这样可以减少很多操作。 2. 将生成的验证码图片转成Base64返回到页面. 3.将验证码存到redis中,设置过期时间。 4.比较。

qq_41922302的博客 248

电子电器架构 --- OEM企标中规定ECU启动时间的目的

电子电器架构 --- OEM企标中规定ECU启动时间的目的

Soly_kun的博客 223

Java实现验证码的制作

验证码概述 为什么使用验证码?   验证码(CAPTCHA)是一种全自动程序。主要是为了区分“进行操作的是不是人”。如果没有验证码机制,将会导致以下的问题: 对特定网站不断进行登录,破解密码; 对某个网站创建账户; 对某个网站提交垃圾数据(灌水贴); 对某个网站进行刷票。 使用Servlet实现验证码   一个验证码包含两个部分:图片和输入框。 1 <s...

weixin_30580943的博客 194

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

java实现验证码的制作

验证码概述 为什么使用验证码?   验证码(CAPTCHA)是一种全自动程序。主要是为了区分“进行操作的是不是人”。如果没有验证码机制,将会导致以下的问题: 对特定网站不断进行登录,破解密码;对某个网站创建账户;对某个网站提交垃圾数据(灌水贴);对某个网站进行刷票。   使用Servlet实现验证码   一个验证码包含两个部分:图片和输入框。 1 s

qq_36014627的博客 470

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

进销存系统_添加图片验证码(8)

一、添加图片验证码 1.1、验证码输出 坐标添加 <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency> 添加验证码基本属性配置 kaptcha.properties # 验证码配置 kapt

付之一笑的专栏 367

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

验证码的java实现

验证码概述 为什么使用验证码?   验证码(CAPTCHA)是一种全自动程序。主要是为了区分“进行操作的是不是人”。如果没有验证码机制,将会导致以下的问题: 对特定网站不断进行登录,破解密码;对某个网站创建账户;对某个网站提交垃圾数据(灌水贴);对某个网站进行刷票。   使用Servlet实现验证码   一个验证码包含两个部分:图片和输入框。 1 s

ptsx0607的专栏 432

shiro-登陆增加一个字段

验证码是为了区分人与电脑,防止电脑代替人冲击系统。在伟大的中国人民人工验证的海洋面前,验证码完全不是个事。 不过一般不是特别热门的系统是不会有人雇佣人民海洋来人工识别验证码的,所有我们的系统还是需要加入验证码机制。 在Java Web系统中验证码世界已经很多种的实现,有些很大很复杂,有些没有维护了,有些验证码人也认证不出来。。。比较合适用的就是Jcaptcha和Kcaptcha。Captcha使

Java_feng的博客 2410

爬虫验证码

我现在使用 phantomJS 截图,然后裁剪得到验证码,再通过Python光学识别获取验证码。 这个过程中遇到 phantomJS 截图大小不一致的问题,我本地的和服务器的图片,验证码的位置不一致。没办法,只好把服务器上的图片 scp 下来,然后更改像素位置。 为什么不直接下载图片下来呢? 每次点击图片,图片都会变化。应该是要将 cookie 和验证码一起提交上去。要验证这个观点,我决定使...

weixin_30344131的博客 161
上一篇: 一文教你学会实现以邮件激活的注册账户代码
下一篇: 用户信息、账号设置。换做是你会怎么做代码实现?
yumuing blog
博客等级 码龄6年 9922粉丝 64原创
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yumuing blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值