因公司项目需要,做了一个图片验证码,但是如何验证是个问题,单纯的将验证码加密后存放到cookie中肯定是不安全的(试想一下,一直拿“ABCD”验证码的加密cookie去验证ABCD)。入库的话成本显的太高。这时大家肯定会想,放到session里面呀!!!没错,放到session里是很合理,但是前提是要考虑两个必要问题,1:如果有人恶意访问,造成大量的session生成,服务器能否受的了? 2:项目做了负载均衡后session如何共享? 这时使用redis就解决了这些问题
参考网上各位前辈的想法及案例,自己在ubuntu上安装了一个rediis 如何安装,详见 ,并写了一个图片验证码session共享的demo代码详见
首先引入依赖,需要引入redis及redis session依赖
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>1.5.4.RELEASE</version>
</dependency>
<!-- redis session -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
然后添加配置
spring:
redis:
database: 0 # Redis数据库索引(默认为0)
host: 192.168.5.247 # Redis服务器地址
port: 6379 # Redis服务器连接端口
password: xzs # Redis服务器连接密码(默认为空)
timeout: 0 # 连接超时时间(毫秒)
pool:
max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 8 # 连接池中的最大空闲连接
min-idle: 0 # 连接池中的最小空闲连接
session:
store-type: none
编写redis配置类,我这里基本没做什么
@Configuration
//设定为60秒session过期
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=60)
public class RedisConfig{
}
编辑启动类
@EnableAutoConfiguration
@ComponentScan(basePackages={"com.xzs"})
@SpringBootApplication
public class RedisDemoApplication extends SpringBootServletInitializer implements EmbeddedServletContainerCustomizer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(RedisDemoApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(RedisDemoApplication.class, args);
}
public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) {
}
}
然后就是我的controller类里的了。
我的验证码字符串使用SHA加盐加密,至于怎么实现怎么生成验证图片都可以去代码里看代码详见
@Controller
public class ImgController {
@RequestMapping(value = "/images/imagecode")
public String imagecode1(HttpServletRequest request, HttpServletResponse response) throws Exception {
String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
OutputStream os = response.getOutputStream();
Map<String, Object> map = VerifyCodeUtils.outputImage(184, 70, os, verifyCode);
String shaCode = EncryptUtil.encrypt(verifyCode + "xzs", "SHA-256");
System.err.println("原始验证码:" + verifyCode + "::::::::::::::加盐xzs使用SHA-256加密后的验证码:" + shaCode);
//获取验证码之前先清空一次
request.getSession().removeAttribute("imgCody");
Object o = request.getSession().getAttribute("imgCody");
if (o == null) {
o = "spring boot 牛逼了!!!有端口" + request.getLocalPort() + "生成";
System.err.println(o.toString() + "::::::::::" + shaCode);
request.getSession().setAttribute("imgCody", shaCode);
}
try {
ImageIO.write((BufferedImage) map.get("image"), "JPEG", os);
} catch (IOException e) {
return "";
}
return null;
}
@GetMapping(value = "/verifiCode")
@ResponseBody
public String imgVrifi(@RequestParam String verifiCode, HttpServletRequest request, HttpServletResponse response) {
String o = (String) request.getSession().getAttribute("imgCody");
System.err.println("获得的session为:" + o);
String shaCode = EncryptUtil.encrypt(verifiCode + "xzs", "SHA-256");
if (o == null) {
return "验证码过期了,重新刷新";
} else {
if (o.equals(shaCode)) {
return "对了,验证码为:" + verifiCode + "::::::session为:" + o;
}
return "验证码错了";
}
}