Captcha验证码不显示
今天在做自己项目的登录功能时出现了验证码能正常获取到,但不能在界面上显示的问题.
1.前端代码
html:
js:
2.后端代码
Controller层:
import com.ark.fitnesshub.common.utils.R;
import com.ark.fitnesshub.core.entity.UserEntity;
import com.ark.fitnesshub.core.form.LoginForm;
import com.ark.fitnesshub.core.form.RegisterForm;
import com.ark.fitnesshub.core.service.CaptchaService;
import com.ark.fitnesshub.core.service.UserService;
import com.ark.fitnesshub.core.service.UserTokenService;
import org.apache.commons.io.IOUtils;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;
@CrossOrigin
@RestController
//@RequestMapping("/entry")
public class EntryController {
@Autowired
private CaptchaService captchaService;
/**
* 验证码
*/
@GetMapping("captcha.jpg")
public void captcha(HttpServletResponse response, String uuid)throws IOException {
response.setHeader("Cache-Control", "no-store, no-cache");
response.setContentType("image/jpeg");
//获取图片验证码
BufferedImage image = captchaService.getCaptcha(uuid);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(image, "jpg", out);
IOUtils.closeQuietly(out);
}
}
Service层(省略Service接口):
import com.ark.fitnesshub.common.exception.RRException;
import com.ark.fitnesshub.common.utils.DateUtils;
import com.ark.fitnesshub.common.utils.PageUtils;
import com.ark.fitnesshub.common.utils.Query;
import com.ark.fitnesshub.core.dao.CaptchaDao;
import com.ark.fitnesshub.core.entity.CaptchaEntity;
import com.ark.fitnesshub.core.service.CaptchaService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.code.kaptcha.Producer;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("captchaService")
public class CaptchaServiceImpl extends ServiceImpl implements CaptchaService {
@Autowired
private Producer producer;
@Override
public BufferedImage getCaptcha(String uuid) {
if(StringUtils.isBlank(uuid)){
throw new RRException("uuid不能为空");
}
//生成文字验证码
String code = producer.createText();
CaptchaEntity captchaEntity = new CaptchaEntity();
captchaEntity.setUuid(uuid);
captchaEntity.setCode(code);
//5分钟后过期
captchaEntity.setExpireTime(DateUtils.addDateMinutes(new Date(), 5));
this.save(captchaEntity);
return producer.createImage(code);
}
}
Entity层:
@Data
@TableName("captcha")
public class CaptchaEntity {
// private static final long serialVersionUID = 1L;
/**
* 随机数,非空非自增
*/
@TableId(type = IdType.INPUT)
private String uuid;
/**
* 验证码,非空
*/
private String code;
/**
* 过期时间
*/
private Date expireTime;
}
3.问题演示
1.前端不报错,能在network中正常显示验证码图片,如下:
但在登录界面上显示加载失败,如下:
2.后端Tomcat不报错,debug日志如下:
数据也正常存入数据库中的captcha表,如下:
我在网上找遍了几乎所有的可能的解决方案,比如在前端的js中将返回的图片流进行定义数据类型ResponseType:' blob' 和'arraybuffer',检查了前后端项目的端口都是对应的(前端项目端口localhost:8081,在main.js文件中的axios的默认请求名为axios.defaults.baseURL = 'http://localhost:8100',后端项目接口为localhost:8100)。
4.问题解决
检查了半天发现是后端对验证码图片的存储问题,将EntryController中的captcha方法中的
response.setHeader("Cache-Control", "no-store,no-cache");
改成:
response.setHeader("Cache-Control", "no-cache");
5.总结
改动的原因是验证码生成后需要缓存在服务器中供客户端获取。遇到问题不要慌,冷静分析按图索骥。