图形验证码
package com.pica.cloud.account.account.server.util.captcha;
public interface Generator {
String generateChars(int size);
}
package com.pica.cloud.account.account.server.util.captcha;
import com.google.common.collect.Range;
import com.google.common.collect.RangeMap;
import com.google.common.collect.TreeRangeMap;
import org.springframework.stereotype.Component;
import java.awt.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
@Component
public class CaptchaGenerator {
protected RangeMap<Integer, CaptchaContext> ctxs = TreeRangeMap.create();
protected List<Generator> gens = new ArrayList();
class NumberLetterGenerator implements Generator {
@Override
public String generateChars(int size) {
return CaptchaUtil.generateUUIDText(size);
}
}
public CaptchaGenerator() throws FontFormatException, IOException {
int h = 40;
ctxs.put(Range.closedOpen(0, h), new CaptchaContext(h * 4, h, (int) (h * 1.2), true));
h *= 2;
ctxs.put(Range.closedOpen(h / 2, h), new CaptchaContext(h * 4, h, (int) (h * 1.2), true));
h *= 2;
ctxs.put(Range.closedOpen(h / 2, Integer.MAX_VALUE), new CaptchaContext(h * 4, h, (int) (h * 1.2), true));
gens.add(new NumberLetterGenerator());
}
@SuppressWarnings("unused")
public byte[] createCaptcha(String text, int width, int height) {
CaptchaContext ctx = ctxs.get(height);
if (ctx == null) {
ctx = ctxs.get(0);
}
return CaptchaUtil.generateImage(text, ctx);
}
public String generateChars(int size) {
int idx = ThreadLocalRandom.current().nextInt(gens.size());
Generator gen = gens.get(idx);
return gen.generateChars(size);
}
}
package com.pica.cloud.account.account.server.service.impl;
import com.pica.cloud.account.account.server.service.CaptchaService;
import com.pica.cloud.account.account.server.util.MemcachedClientWrapper;
import com.pica.cloud.account.account.server.util.captcha.CaptchaGenerator;
import com.pica.cloud.account.account.server.util.captcha.CaptchaToken;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
public class CaptchaServiceImpl implements CaptchaService {
private final int size = 5;
private final String CAPTCHA_PREFIX = "captcha-";
@Autowired
private CaptchaGenerator agent;
@Autowired
MemcachedClientWrapper cache;
@Override
public CaptchaToken generateToken(int width, int height) {
String origin = agent.generateChars(size);
byte[] buf = agent.createCaptcha(origin, width, height);
CaptchaToken ret = new CaptchaToken();
ret.setBuf(buf);
ret.setOrigin(origin);
ret.setToken(DigestUtils.md5Hex(UUID.randomUUID().toString()));
cache.set(CAPTCHA_PREFIX + ret.getToken(), origin);
return ret;
}
@Override
public boolean acknowledge(String token, String answer) {
String origin = cache.get(CAPTCHA_PREFIX + token);
cache.remove(CAPTCHA_PREFIX + token);
if (origin != null && answer != null) {
return origin.compareToIgnoreCase(answer) == 0;
}
return false;
}
}
package com.pica.cloud.account.account.server.util.captcha;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.Base64;
public class CaptchaToken {
protected String token;
@JsonIgnore
protected byte[] buf;
@JsonIgnore
protected String origin;
protected String content;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public byte[] getBuf() {
return buf;
}
public void setBuf(byte[] buf) {
this.buf = buf;
setContent(Base64.getEncoder().encodeToString(this.buf));
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
}
package com.pica.cloud.account.account.server.util.captcha;
import org.apache.commons.io.IOUtils;
import java.awt.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
public class CaptchaContext {
final Random rnd = ThreadLocalRandom.current();
final int fontCount = 4;
public int width;
public int height;
public float fontSize;
public boolean showGrid;
public int gridSize = 1 + rnd.nextInt(10);
public int rotationAmplitude = rnd.nextInt(10);
public int scaleAmplitude = 2 * rotationAmplitude;
public Font font;
static byte[][] fontDatas = new byte[4][];
static {
try {
InputStream fontStream = CaptchaGenerator.class.getClassLoader().getResourceAsStream("1.ttf");
fontDatas[0] = IOUtils.toByteArray(fontStream);
fontStream.close();
fontStream = CaptchaGenerator.class.getClassLoader().getResourceAsStream("2.ttf");
fontDatas[1] = IOUtils.toByteArray(fontStream);
fontStream.close();
fontStream = CaptchaGenerator.class.getClassLoader().getResourceAsStream("3.ttf");
fontDatas[2] = IOUtils.toByteArray(fontStream);
fontStream.close();
fontStream = CaptchaGenerator.class.getClassLoader().getResourceAsStream("4.ttf");
fontDatas[3] = IOUtils.toByteArray(fontStream);
fontStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public