Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.fastchar.captcha.out.FastOutCaptchaOfClick Maven / Gradle / Ivy
package com.fastchar.captcha.out;
import com.fastchar.captcha.FastCaptchaConfig;
import com.fastchar.core.FastAction;
import com.fastchar.core.FastChar;
import com.fastchar.out.FastOut;
import com.fastchar.servlet.http.FastHttpServletResponse;
import com.fastchar.utils.FastMD5Utils;
import com.fastchar.utils.FastNumberUtils;
import com.fastchar.utils.FastStringUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.List;
import java.util.*;
/**
* 看图依次点击文字位置
*/
public class FastOutCaptchaOfClick extends FastOut {
private static final String DEFAULT_CAPTCHA_KEY = "FastChar-Captcha";
private static final Color[] SHADOW_COLOR = new Color[]{
Color.BLACK,
Color.RED,
Color.BLUE,
Color.YELLOW,
Color.GREEN,
Color.MAGENTA
};
private static final Set RANDOM_BACKGROUND_INDEX = new HashSet<>();
public FastOutCaptchaOfClick() {
this.contentType = "image/jpeg";
}
@Override
public void response(FastAction action) throws Exception {
FastHttpServletResponse response = action.getResponse();
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setStatus(getStatus());
response.setContentType(toContentType(action));
List keys = new ArrayList<>(5);
for (int i = 0; i < 5; i++) {
keys.add(String.valueOf(randomChar()));
}
outCaptcha(action, keys);
}
public boolean validateCaptcha(FastAction action, List points) {
String captchaKey = action.getParam("captchaKey", DEFAULT_CAPTCHA_KEY);
List captcha = action.getSession(captchaKey);
if (captcha == null) {
return false;
}
if (captcha.isEmpty()) {
return false;
}
if (points.size() > captcha.size()) {
return false;
}
for (int i = 0; i < points.size(); i++) {
String pointStr = points.get(i);
String[] pointArray = pointStr.split(",");
int x = FastNumberUtils.formatToInt(pointArray[0]);
int y = FastNumberUtils.formatToInt(pointArray[1]);
Rectangle rectangle = captcha.get(i);
if (!rectangle.contains(x, y)) {
return false;
}
}
String value = FastMD5Utils.MD5(FastStringUtils.buildUUID());
action.setSession(captchaKey, value);
action.setSession("validateCode", value);
return true;
}
public List getContents(FastAction action) {
String captchaKey = action.getParam("captchaKey", DEFAULT_CAPTCHA_KEY);
return action.getSession(captchaKey + "Content");
}
public void resetCaptcha(FastAction action) {
String captchaKey = action.getParam("captchaKey", DEFAULT_CAPTCHA_KEY);
action.removeSession(captchaKey);
}
private void outCaptcha(FastAction action, List contents) throws Exception {
String captchaKey = action.getParam("captchaKey", DEFAULT_CAPTCHA_KEY);
FastCaptchaConfig config = FastChar.getConfig(FastCaptchaConfig.class);
List captchaFonts = config.getCaptchaFonts();
List captchaBackgroundImages = config.getCaptchaBackgroundImages();
if (RANDOM_BACKGROUND_INDEX.size() >= captchaBackgroundImages.size()) {
RANDOM_BACKGROUND_INDEX.clear();
}
int backgroundIndex;
do {
backgroundIndex = new Random().nextInt(captchaBackgroundImages.size());
} while (RANDOM_BACKGROUND_INDEX.contains(backgroundIndex));
RANDOM_BACKGROUND_INDEX.add(backgroundIndex);
URL backgroundImg = captchaBackgroundImages.get(backgroundIndex);
Map stringFont = new HashMap<>(contents.size());
for (String string : contents) {
if (config.isSimple()) {
stringFont.put(string, config.getSimpleFontURL());
}else{
stringFont.put(string, captchaFonts.get(new Random().nextInt(captchaFonts.size())));
}
}
Image backgroundImgIO = ImageIO.read(backgroundImg);
int imgIOWidth = backgroundImgIO.getWidth(null);
int imgIOHeight = backgroundImgIO.getHeight(null);
BufferedImage bufferedImage = new BufferedImage(imgIOWidth, imgIOHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = bufferedImage.createGraphics();
antialiasing(graphics2D);
graphics2D.drawImage(backgroundImgIO.getScaledInstance(imgIOWidth, imgIOHeight, Image.SCALE_SMOOTH), 0, 0, null);
int directionType = new Random().nextInt(2);
int index = 0;
float margin = Math.min(imgIOHeight, imgIOWidth) * 0.2f;
float avgHSpace = imgIOWidth / (float) stringFont.size();
float avgVSpace = imgIOHeight / (float) stringFont.size();
float fontSize = Math.min(imgIOHeight, imgIOWidth) / (contents.size() * 1.5f);
int shadowSize = 5;//投影的大小
int span = 5;//允许超出边界距离
Map stringRectangle = new HashMap<>(contents.size());
for (Map.Entry stringURLEntry : stringFont.entrySet()) {
String content = stringURLEntry.getKey();
Font font = getFont(fontSize, stringURLEntry.getValue());
graphics2D.setFont(font);
FontMetrics fontMetrics = graphics2D.getFontMetrics();
Rectangle2D contentBound = fontMetrics.getStringBounds(content, graphics2D);
float y;
float x;
if (directionType == 0) {//横向
x = index * avgHSpace;
y = (float) FastNumberUtils.random(fontMetrics.getAscent(), imgIOHeight - contentBound.getHeight()) + fontMetrics.getAscent();
} else {
y = index * avgVSpace + fontMetrics.getAscent();
x = (float) FastNumberUtils.random(0, imgIOWidth - contentBound.getWidth());
}
x = Math.max(x, margin);
y = Math.max(y, margin);
if (config.isSimple()) {
graphics2D.setColor(Color.WHITE);
}else{
graphics2D.setColor(SHADOW_COLOR[new Random().nextInt(SHADOW_COLOR.length)]);
}
graphics2D.drawString(content, x + shadowSize, y + shadowSize);
Color color1 = randomColor();
Color color2 = randomColor();
if (config.isSimple()) {
graphics2D.setColor(Color.BLACK);
}else{
GradientPaint paint = new GradientPaint(20, 20, color1, (float) (contentBound.getWidth() * 0.6), (float) (contentBound.getHeight() * 0.7), color2, true);
graphics2D.setPaint(paint);// 设置渐变
}
graphics2D.drawString(content, x, y);
stringRectangle.put(content, new Rectangle((int) x - span, (int) y - fontMetrics.getAscent() - span, (int) contentBound.getWidth() + shadowSize + span, (int) contentBound.getHeight() + shadowSize + span));
index++;
}
Collections.shuffle(contents);
List responseContent = new ArrayList<>(contents.size());
for (String key : contents) {
responseContent.add(stringRectangle.get(key));
}
action.setSession(captchaKey, responseContent);
action.setSession(captchaKey + "Content", contents);
try (OutputStream outputStream = action.getResponse().getOutputStream()) {
ImageIO.write(bufferedImage, "jpg", outputStream);
outputStream.flush();
}
}
private void antialiasing(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
}
private Font getFont(double fontSize, URL fontURL) throws IOException, FontFormatException {
Map attrs = new HashMap<>();
attrs.put(TextAttribute.SIZE, fontSize);
attrs.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
if (new Random().nextInt(10) % 2 == 0) {
attrs.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
}
try (InputStream fontStream = fontURL.openStream()) {
Font font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
return font.deriveFont(attrs);
}
}
private char randomChar() {
String str = "";
int heightPos;
int lowPos;
Random random = new Random();
heightPos = (176 + Math.abs(random.nextInt(39)));
lowPos = (161 + Math.abs(random.nextInt(93)));
byte[] b = new byte[2];
b[0] = (Integer.valueOf(heightPos)).byteValue();
b[1] = (Integer.valueOf(lowPos)).byteValue();
try {
str = new String(b, "GBK");
} catch (Exception e) {
e.printStackTrace();
}
return str.charAt(0);
}
private Color randomColor() {
Random random = new Random();
int r = random.nextInt(255);
int g = random.nextInt(255);
int b = random.nextInt(255);
return new Color(r, g, b, 255);
}
}