当前位置:网站首页>Verification code redis practice summary
Verification code redis practice summary
2022-06-23 10:25:00 【cfcoolya】
One Verification Code +redis application
Design thinking
1.0 background
Recently, I have been developing the function module functions of the open management platform of liaoshitong institution .
This module involves registering 、 Sign in 、 Entry and other functions .
The technologies involved are SpringBoot、Mybatis、Spring Security、Jwt、Npm、vue-cli、vue-router、vuex、element-ui
1.1 Verification code generation ideas
Back end thinking :
a. Store the verification code in redis,( key value Time Company ) Where the key consists of a constant +uuid Splicing , Values are randomly generated 4 A string , Time is 2 minute .
b. utilize BufferedImage Output verification code picture stream , Among them Base64.encode conversion ByteArrayutputStream flow ( The advantage of this is to reduce http Request times to reduce the burden on the web server )
c. Perform the following verification after logging in Pass key , Go to redis Inside looking for , There will be the following .
If redis Return to empty , It indicates that the verification code is invalid .
If redis Return is not empty , But not equally , Description verification code input error .
Front end thinking :
<el-row class="login-form-item">
<el-col :span="12">
<el-input type="input" v-model="validCode" placeholder=" Please enter the verification code " prefix-icon="el-icon-circle-check"></el-input>
</el-col>
<el-col :span="6" :offset="1">
<img class="login-code-img" :src="codeUrl" @click.prevent="getCode">
</el-col>
</el-row>
methods: {
getCode() {
getCodeImg().then(res => {
this.codeUrl = "data:image/gif;base64," + res.img;
this.uuid = res.uuid;
});
},
}
// Get verification code
export function getCodeImg() {
return request({
url: '/captchaImage',
method: 'get'
})
}
Related utility class
2.0 Verification code tool class
a. Generate random string
String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
b. Generate pictures
int w = 111, h = 36;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
VerifyCodeUtils.outputImage(w, h, stream, verifyCode);
public class VerifyCodeUtils
{
// Use to Algerian typeface , Fonts need to be installed if not in the system , The font only shows uppercase , Removed 1,0,i,o A few confusing characters
public static final String VERIFY_CODES = "123456789ABCDEFGHJKLMNPQRSTUVWXYZ";
private static Random random = new SecureRandom();
/**
* Use the system default character source to generate the verification code
*
* @param verifySize Length of verification code
* @return
*/
public static String generateVerifyCode(int verifySize)
{
return generateVerifyCode(verifySize, VERIFY_CODES);
}
/**
* Generate the verification code using the specified source
*
* @param verifySize Length of verification code
* @param sources Verify source of codeword
* @return
*/
public static String generateVerifyCode(int verifySize, String sources)
{
if (sources == null || sources.length() == 0)
{
sources = VERIFY_CODES;
}
int codesLen = sources.length();
Random rand = new Random(System.currentTimeMillis());
StringBuilder verifyCode = new StringBuilder(verifySize);
for (int i = 0; i < verifySize; i++)
{
verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));
}
return verifyCode.toString();
}
/**
* Output the specified captcha picture stream
*
* @param w
* @param h
* @param os
* @param code
* @throws IOException
*/
public static void outputImage(int w, int h, OutputStream os, String code) throws IOException
{
int verifySize = code.length();
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Random rand = new Random();
Graphics2D g2 = image.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = new Color[5];
Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA,
Color.ORANGE, Color.PINK, Color.YELLOW };
float[] fractions = new float[colors.length];
for (int i = 0; i < colors.length; i++)
{
colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
fractions[i] = rand.nextFloat();
}
Arrays.sort(fractions);
g2.setColor(Color.GRAY);// Set border color
g2.fillRect(0, 0, w, h);
Color c = getRandColor(200, 250);
g2.setColor(c);// Set background color
g2.fillRect(0, 2, w, h - 4);
// Draw interference line
Random random = new Random();
g2.setColor(getRandColor(160, 200));// Set the color of the line
for (int i = 0; i < 20; i++)
{
int x = random.nextInt(w - 1);
int y = random.nextInt(h - 1);
int xl = random.nextInt(6) + 1;
int yl = random.nextInt(12) + 1;
g2.drawLine(x, y, x + xl + 40, y + yl + 20);
}
// Add noise
float yawpRate = 0.05f;// Noise rate
int area = (int) (yawpRate * w * h);
for (int i = 0; i < area; i++)
{
int x = random.nextInt(w);
int y = random.nextInt(h);
int rgb = getRandomIntColor();
image.setRGB(x, y, rgb);
}
shear(g2, w, h, c);// Distort the picture
g2.setColor(getRandColor(100, 160));
int fontSize = h - 4;
Font font = new Font("Algerian", Font.ITALIC, fontSize);
g2.setFont(font);
char[] chars = code.toCharArray();
for (int i = 0; i < verifySize; i++)
{
AffineTransform affine = new AffineTransform();
affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1),
(w / verifySize) * i + fontSize / 2, h / 2);
g2.setTransform(affine);
g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);
}
g2.dispose();
ImageIO.write(image, "jpg", os);
}
private static Color getRandColor(int fc, int bc)
{
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
private static int getRandomIntColor()
{
int[] rgb = getRandomRgb();
int color = 0;
for (int c : rgb)
{
color = color << 8;
color = color | c;
}
return color;
}
private static int[] getRandomRgb()
{
int[] rgb = new int[3];
for (int i = 0; i < 3; i++)
{
rgb[i] = random.nextInt(255);
}
return rgb;
}
private static void shear(Graphics g, int w1, int h1, Color color)
{
shearX(g, w1, h1, color);
shearY(g, w1, h1, color);
}
private static void shearX(Graphics g, int w1, int h1, Color color)
{
int period = random.nextInt(2);
boolean borderGap = true;
int frames = 1;
int phase = random.nextInt(2);
for (int i = 0; i < h1; i++)
{
double d = (double) (period >> 1)
* Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
g.copyArea(0, i, w1, 1, (int) d, 0);
if (borderGap)
{
g.setColor(color);
g.drawLine((int) d, i, 0, i);
g.drawLine((int) d + w1, i, w1, i);
}
}
}
private static void shearY(Graphics g, int w1, int h1, Color color)
{
int period = random.nextInt(40) + 10; // 50;
boolean borderGap = true;
int frames = 20;
int phase = 7;
for (int i = 0; i < w1; i++)
{
double d = (double) (period >> 1)
* Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
g.copyArea(i, 0, 1, h1, 0, (int) d);
if (borderGap)
{
g.setColor(color);
g.drawLine(i, (int) d, i, 0);
g.drawLine(i, (int) d + h1, i, h1);
}
}
}
}
2.1 ID Generator tool class
Unique identification
String uuid = IdUtils.simpleUUID();
public class IdUtils
{
/**
* Get random UUID
*
* @return Random UUID
*/
public static String randomUUID()
{
return UUID.randomUUID().toString();
}
/**
* A simplified UUID, Remove the horizontal line
*
* @return A simplified UUID, Remove the horizontal line
*/
public static String simpleUUID()
{
return UUID.randomUUID().toString(true);
}
/**
* Get random UUID, Use better performance ThreadLocalRandom Generate UUID
*
* @return Random UUID
*/
public static String fastUUID()
{
return UUID.fastUUID().toString();
}
/**
* A simplified UUID, Remove the horizontal line , Use better performance ThreadLocalRandom Generate UUID
*
* @return A simplified UUID, Remove the horizontal line
*/
public static String fastSimpleUUID()
{
return UUID.fastUUID().toString(true);
}
}
2.2 redis Tool class
@Component
public class RedisCache
{
@Autowired
public RedisTemplate redisTemplate;
/**
* Cache basic objects ,Integer、String、 Entity class, etc
*
* @param key Cached key value
* @param value The value of the cache
* @return Cached objects
*/
public <T> ValueOperations<String, T> setCacheObject(String key, T value)
{
ValueOperations<String, T> operation = redisTemplate.opsForValue();
operation.set(key, value);
return operation;
}
/**
* Cache basic objects ,Integer、String、 Entity class, etc
*
* @param key Cached key value
* @param value The value of the cache
* @param timeout Time
* @param timeUnit The granularity of time
* @return Cached objects
*/
public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit)
{
ValueOperations<String, T> operation = redisTemplate.opsForValue();
operation.set(key, value, timeout, timeUnit);
return operation;
}
/**
* Get the cached base object .
*
* @param key Cache key values
* @return Cache the data corresponding to the key value
*/
public <T> T getCacheObject(String key)
{
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* Delete a single object
*
* @param key
*/
public void deleteObject(String key)
{
redisTemplate.delete(key);
}
/**
* Delete collection object
*
* @param collection
*/
public void deleteObject(Collection collection)
{
redisTemplate.delete(collection);
}
/**
* cache List data
*
* @param key Cached key value
* @param dataList To be cached List data
* @return Cached objects
*/
public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList)
{
ListOperations listOperation = redisTemplate.opsForList();
if (null != dataList)
{
int size = dataList.size();
for (int i = 0; i < size; i++)
{
listOperation.leftPush(key, dataList.get(i));
}
}
return listOperation;
}
/**
* Get cached list object
*
* @param key Cached key value
* @return Cache the data corresponding to the key value
*/
public <T> List<T> getCacheList(String key)
{
List<T> dataList = new ArrayList<T>();
ListOperations<String, T> listOperation = redisTemplate.opsForList();
Long size = listOperation.size(key);
for (int i = 0; i < size; i++)
{
dataList.add(listOperation.index(key, i));
}
return dataList;
}
/**
* cache Set
*
* @param key Cache key values
* @param dataSet Cached data
* @return Objects that cache data
*/
public <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet)
{
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext())
{
setOperation.add(it.next());
}
return setOperation;
}
/**
* Get cached set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(String key)
{
Set<T> dataSet = new HashSet<T>();
BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key);
dataSet = operation.members();
return dataSet;
}
/**
* cache Map
*
* @param key
* @param dataMap
* @return
*/
public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap)
{
HashOperations hashOperations = redisTemplate.opsForHash();
if (null != dataMap)
{
for (Map.Entry<String, T> entry : dataMap.entrySet())
{
hashOperations.put(key, entry.getKey(), entry.getValue());
}
}
return hashOperations;
}
/**
* Get cached Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(String key)
{
Map<String, T> map = redisTemplate.opsForHash().entries(key);
return map;
}
/**
* Get the list of cached basic objects
*
* @param pattern String prefix
* @return The object list
*/
public Collection<String> keys(String pattern)
{
return redisTemplate.keys(pattern);
}
/**
* Specify cache expiration time
*
* @param key key
* @param time Time ( second )
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* according to key Get expiration time
*
* @param key key Not for null
* @return Time ( second ) return 0 Stands for permanent validity
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* Judge key Whether there is
*
* @param key key
* @return true There is false non-existent
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* Delete cache
*
* @param key You can pass a value Or more
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
//============================String=============================
/**
* Normal cache fetch
*
* @param key key
* @return value
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* Normal cache put in
*
* @param key key
* @param value value
* @return true success false Failure
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* The normal cache is put in and set the time
*
* @param key key
* @param value value
* @param time Time ( second ) time Be greater than 0 If time Less than or equal to 0 Will be set indefinitely
* @return true success false Failure
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* Increasing
*
* @param key key
* @param delta How much more should I add ( Greater than 0)
* @return
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException(" The increment factor must be greater than 0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* Decline
*
* @param key key
* @param delta To cut it down a few ( Less than 0)
* @return
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException(" The decline factor must be greater than 0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
//================================Map=================================
/**
* HashGet
*
* @param key key Not for null
* @param item term Not for null
* @return value
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* obtain hashKey All the corresponding key values
*
* @param key key
* @return Corresponding multiple key values
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
*
* @param key key
* @param map Corresponding to multiple key values
* @return true success false Failure
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet And set the time
*
* @param key key
* @param map Corresponding to multiple key values
* @param time Time ( second )
* @return true success false Failure
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* To a piece of hash Put data in the table , If it doesn't exist, it will create
*
* @param key key
* @param item term
* @param value value
* @return true success false Failure
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* To a piece of hash Put data in the table , If it doesn't exist, it will create
*
* @param key key
* @param item term
* @param value value
* @param time Time ( second ) Be careful : If there is already hash Watch has time , This will replace the original time
* @return true success false Failure
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* Delete hash The values in the table
*
* @param key key Not for null
* @param item term Can make multiple Not for null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* Judge hash Whether there is a value of this item in the table
*
* @param key key Not for null
* @param item term Not for null
* @return true There is false non-existent
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash Increasing If it doesn't exist , It creates a And return the added value to
*
* @param key key
* @param item term
* @param by How much more should I add ( Greater than 0)
* @return
*/
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash Decline
*
* @param key key
* @param item term
* @param by Remember less ( Less than 0)
* @return
*/
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
//============================set=============================
/**
* according to key obtain Set All the values in
*
* @param key key
* @return
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* according to value From a set Query in , Whether there is
*
* @param key key
* @param value value
* @return true There is false non-existent
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* Put data into set cache
*
* @param key key
* @param values value It can be more than one
* @return The number of successes
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* take set Data is put into the cache
*
* @param key key
* @param time Time ( second )
* @param values value It can be more than one
* @return The number of successes
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* obtain set The length of the cache
*
* @param key key
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* The removal value is value Of
*
* @param key key
* @param values value It can be more than one
* @return Number of removed
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//===============================list=================================
/**
* obtain list The contents of the cache
*
* @param key key
* @param start Start
* @param end end 0 To -1 For all values
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* obtain list The length of the cache
*
* @param key key
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* Through the index obtain list The value in
*
* @param key key
* @param index Indexes index>=0 when , 0 Header ,1 The second element , By analogy ;index<0 when ,-1, Tail ,-2 The next to last element , By analogy
* @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* take list Put into cache
*
* @param key key
* @param value value
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* take list Put into cache
*
* @param key key
* @param value value
* @param time Time ( second )
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* take list Put into cache
*
* @param key key
* @param value value
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* take list Put into cache
*
* @param key key
* @param value value
* @param time Time ( second )
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* Modify according to the index list A piece of data in
*
* @param key key
* @param index Indexes
* @param value value
* @return
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* remove N The values are value
*
* @param key key
* @param count How many removed
* @param value value
* @return Number of removed
*/
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}
边栏推荐
- 2021-05-11抽象类
- mysql innodb 的 redo log buffer 中未 commit 的事务持久化到 redo log 后,万一事务 rollback 了怎么办?redo log 怎么处理这个事务操作?
- 安装typescript环境并开启VSCode自动监视编译ts文件为js文件
- Comic | code review is driving me crazy!
- Lu Qi invests in quantum computing for the first time
- Bugs encountered in Oracle
- 2021-04-15
- 解决audio自动播放无效问题
- Golang quick start (3)
- 2021-05-12内部类
猜你喜欢
随机推荐
一个优秀速开发框架是什么样的?
2021-05-11 instanceof and type conversion
Build a QQ robot to wake up your girlfriend
The era of copilot free is over! The official version is 67 yuan / month, and the student party and the defenders of popular open source projects can prostitute for nothing
R和RStudio下载安装详细步骤
NOI OJ 1.3 11:计算浮点数相除的余数 C语言
Dr. Sun Jian was commemorated at the CVPR conference. The best student thesis was awarded to Tongji Ali. Lifeifei won the huangxutao Memorial Award
解决预览pdf不能下载的问题
Golang quick start (1)
Nuxt.js spa与ssr的区别
thymeleaf如何取url中请求参数值?
SQL教程之SQL 中数据透视表的不同方法
Alimentation des animaux de compagnie basée sur stm32
Successful experience in postgraduate entrance examination for MTI master of English translation major of Beijing University of science and technology in 2023
Unable to enter the system normally, press F8 to select other items to try to enter
JVM简单入门-01
Cool photo album code, happy birthday to the object!
2021-05-10 method rewrite polymorphism considerations
CVPR大会现场纪念孙剑博士,最佳学生论文授予同济阿里,李飞飞获黄煦涛纪念奖...
2021-05-11static关键字








