0%

springboot结合redis实现登录验证码校验

1.添加redis和第三方验证码库

1
2
3
4
5
6
7
8
9
10
11
 <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>cn.apiclub.tool</groupId>
<artifactId>simplecaptcha</artifactId>
<version>1.2.2</version>
</dependency>
</dependencies>

2.添加redis配置

1
2
3
4
5
6
7
8
9
10
11
12
#spring
spring:
redis:
database: 4
host: localhost
port: 6379
timeout: 2000
pool:
max-idle: 8
min-idle: 0
max-active: 8
max-wait: -1

3.添加redis配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package cn.xmp.generator.demo.user.config;

import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
* <p>
* <p>
*
* @author xiemopeng
* @since 2019/2/26
*/

public class RedisConfig {
@Bean
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}

@Bean
RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, String> template = new RedisTemplate<String, String>();
template.setConnectionFactory(jedisConnectionFactory());

template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
return template;
}
}

4.配置验证码过期时间,宽高

1
2
3
4
redis:
captchaExpires: 180
captchaW: 200
captchaH: 60
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package cn.xmp.generator.demo.user.web;

import cn.apiclub.captcha.Captcha;
import cn.apiclub.captcha.backgrounds.GradiatedBackgroundProducer;
import cn.apiclub.captcha.gimpy.FishEyeGimpyRenderer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
* <p>
* <p>
*
* @author xiemopeng
* @since 2019/2/26
*/

@Slf4j
@RestController
@RequestMapping("captcha")
public class CaptchaModule {

@Autowired
private RedisTemplate<String, String> redisTemplate;
@Value("${redis.captchaExpires}")
private int captchaExpires; //超时时间3min
@Value("${redis.captchaW}")
private int captchaW; //验证码宽度
@Value("${redis.captchaH}")
private int captchaH; //验证码高度

@RequestMapping(value = "getcaptcha", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)

public
@ResponseBody
byte[] getCaptcha(HttpServletResponse response) {
//生成验证码
String uuid = UUID.randomUUID().toString();
Captcha captcha = new Captcha.Builder(captchaW, captchaH)
.addText().addBackground(new GradiatedBackgroundProducer(Color.red, Color.cyan))
.gimp(new FishEyeGimpyRenderer())
.build();

log.info("验证码答案:{}", captcha.getAnswer());
log.info("验证码配置:{},{},{}", captchaExpires,captchaW,captchaH);
//将验证码以<key,value>形式缓存到redis
redisTemplate.opsForValue().set(uuid, captcha.getAnswer(), captchaExpires, TimeUnit.SECONDS);
//将验证码key,及验证码的图片返回
Cookie cookie = new Cookie("CaptchaCode", uuid);
response.addCookie(cookie);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
try {
ImageIO.write(captcha.getImage(), "png", bao);
return bao.toByteArray();
} catch (IOException e) {
log.info("获取验证码异常:{}", e.getMessage());
return null;
}
}
}

5.修改前面的jwt-token校验逻辑

在校验token前先校验验证码是否正确

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package cn.xmp.generator.demo.user.web;

/**
* <p>
* <p>
*
* @author xiemopeng
* @since 2019/2/14
*/

import cn.xmp.generator.demo.user.config.Audience;
import cn.xmp.generator.demo.user.entity.AppUser;
import cn.xmp.generator.demo.user.enums.ReturnCodeEnum;
import cn.xmp.generator.demo.user.jwt.model.AccessToken;
import cn.xmp.generator.demo.user.jwt.model.LoginPara;
import cn.xmp.generator.demo.user.jwt.utils.JwtHelper;
import cn.xmp.generator.demo.user.model.response.BaseResponse;
import cn.xmp.generator.demo.user.service.IAppUserService;
import cn.xmp.generator.demo.user.utils.BackResponseUtil;
import cn.xmp.generator.demo.user.utils.MyUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;


@RestController
@Slf4j
@Scope("prototype")
@AllArgsConstructor
public class JsonWebToken {
private IAppUserService appUserService;

private Audience audienceEntity;
@Autowired
private RedisTemplate<String, String> redisTemplate;

@RequestMapping(value = "/oauth/token", method = RequestMethod.POST)
@ResponseBody
public Object getAccessToken(@RequestBody LoginPara loginPara) {
BaseResponse response = new BaseResponse();
log.info("获取token入参{}", loginPara);
try {
String captchaCode = loginPara.getCaptchaCode();
try {
if (captchaCode == null) {
response = BackResponseUtil.getBaseResponse(ReturnCodeEnum.CODE_1005.getCode());
response.setMessage(ReturnCodeEnum.CODE_1006.getValue());
return response;
}
String captchaValue = redisTemplate.opsForValue().get(captchaCode);
if (captchaValue == null) {
response = BackResponseUtil.getBaseResponse(ReturnCodeEnum.CODE_1005.getCode());
response.setMessage(ReturnCodeEnum.CODE_1010.getValue());
return response;
}
redisTemplate.delete(captchaCode);

if (captchaValue.compareTo(loginPara.getCaptchaValue()) != 0) {
response = BackResponseUtil.getBaseResponse(ReturnCodeEnum.CODE_1005.getCode());
response.setMessage(ReturnCodeEnum.CODE_1010.getValue());
return response;
}
} catch (Exception e) {
response = BackResponseUtil.getBaseResponse(ReturnCodeEnum.CODE_1005.getCode());
response.setMessage(ReturnCodeEnum.CODE_1010.getValue());
return response;
}

//验证用户名密码
AppUser user = new AppUser();
user.setName(loginPara.getUserName());
user.setPassword(loginPara.getPassword());
log.info("用户登录入参:{}", user.toString());
BaseResponse userResponse = appUserService.login(user);
log.info("用户登录返回:{}", userResponse);
user = (AppUser) userResponse.getDataInfo();
if (user == null) {
response = BackResponseUtil.getBaseResponse(ReturnCodeEnum.CODE_1002.getCode());
return response;
}
//拼装accessToken
String accessToken = JwtHelper.createJWT(loginPara.getUserName(), String.valueOf(user.getId()),
audienceEntity.getClientId(), audienceEntity.getName(),
audienceEntity.getExpiresSecond() * 1000, audienceEntity.getBase64Secret());

//返回accessToken
AccessToken accessTokenEntity = new AccessToken();
accessTokenEntity.setAccess_token(accessToken);
accessTokenEntity.setExpires_in(audienceEntity.getExpiresSecond());
accessTokenEntity.setToken_type("bearer");
response = BackResponseUtil.getBaseResponse(ReturnCodeEnum.CODE_1000.getCode());
response.setDataInfo(accessTokenEntity);
log.info("获取token返回{}", response);
return response;

} catch (Exception ex) {
log.info("获取token异常:{}", ex);
response = BackResponseUtil.getBaseResponse(ReturnCodeEnum.CODE_1004.getCode());
}
return response;
}

}

6.测试

启动redis服务端,本文使用的windows版测试

1551318120812

获取验证码及cookie

15513176998231551317722565
通过key(cookie)获取验证码校验验证码
1551317919233

-------------本文结束感谢您的阅读-------------