Sfoglia il codice sorgente

RandomColor captcha

Crystal.Sea 3 anni fa
parent
commit
9b67ce8160

+ 94 - 0
maxkey-authentications/maxkey-authentication-captcha/src/main/java/com/google/code/kaptcha/impl/LightNoise.java

@@ -0,0 +1,94 @@
+package com.google.code.kaptcha.impl;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+import java.util.Random;
+
+import com.google.code.kaptcha.NoiseProducer;
+import com.google.code.kaptcha.util.Configurable;
+
+/**
+ * The default implementation of {@link NoiseProducer}, adds a noise on an
+ * image.
+ */
+public class LightNoise extends Configurable implements NoiseProducer
+{
+	/**
+	 * Draws a noise on the image. The noise curve depends on the factor values.
+	 * Noise won't be visible if all factors have the value > 1.0f
+	 * 
+	 * @param image
+	 *            the image to add the noise to
+	 * @param factorOne
+	 * @param factorTwo
+	 * @param factorThree
+	 * @param factorFour
+	 */
+	public void makeNoise(BufferedImage image, float factorOne,
+			float factorTwo, float factorThree, float factorFour)
+	{
+		Color color = getConfig().getNoiseColor();
+
+		// image size
+		int width = image.getWidth();
+		int height = image.getHeight();
+
+		// the points where the line changes the stroke and direction
+		Point2D[] pts = null;
+		Random rand = new SecureRandom();
+
+		// the curve from where the points are taken
+		CubicCurve2D cc = new CubicCurve2D.Float(width * factorOne, height
+				* rand.nextFloat(), width * factorTwo, height
+				* rand.nextFloat(), width * factorThree, height
+				* rand.nextFloat(), width * factorFour, height
+				* rand.nextFloat());
+
+		// creates an iterator to define the boundary of the flattened curve
+		PathIterator pi = cc.getPathIterator(null, 2);
+		Point2D tmp[] = new Point2D[200];
+		int i = 0;
+
+		// while pi is iterating the curve, adds points to tmp array
+		while (!pi.isDone())
+		{
+			float[] coords = new float[6];
+			switch (pi.currentSegment(coords))
+			{
+				case PathIterator.SEG_MOVETO:
+				case PathIterator.SEG_LINETO:
+					tmp[i] = new Point2D.Float(coords[0], coords[1]);
+			}
+			i++;
+			pi.next();
+		}
+
+		pts = new Point2D[i];
+		System.arraycopy(tmp, 0, pts, 0, i);
+
+		Graphics2D graph = (Graphics2D) image.getGraphics();
+		graph.setRenderingHints(new RenderingHints(
+				RenderingHints.KEY_ANTIALIASING,
+				RenderingHints.VALUE_ANTIALIAS_ON));
+
+		graph.setColor(color);
+
+		// for the maximum 3 point change the stroke and direction
+		for (i = 0; i < pts.length - 1; i++)
+		{
+			if (i < 3)
+				graph.setStroke(new BasicStroke(0.7f * (2 - i)));
+			graph.drawLine((int) pts[i].getX(), (int) pts[i].getY(),
+					(int) pts[i + 1].getX(), (int) pts[i + 1].getY());
+		}
+
+		graph.dispose();
+	}
+}

+ 50 - 0
maxkey-authentications/maxkey-authentication-captcha/src/main/java/com/google/code/kaptcha/impl/Ripple.java

@@ -0,0 +1,50 @@
+package com.google.code.kaptcha.impl;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+import com.google.code.kaptcha.GimpyEngine;
+import com.google.code.kaptcha.NoiseProducer;
+import com.google.code.kaptcha.util.Configurable;
+import com.jhlabs.image.RippleFilter;
+import com.jhlabs.image.TransformFilter;
+import com.jhlabs.image.WaterFilter;
+
+/**
+ * {@link WaterRipple} adds water ripple effect to an image.
+ */
+public class Ripple extends Configurable implements GimpyEngine
+{
+	/**
+	 * Applies distortion by adding water ripple effect.
+	 *
+	 * @param baseImage the base image
+	 * @return the distorted image
+	 */
+	public BufferedImage getDistortedImage(BufferedImage baseImage)
+	{
+		NoiseProducer noiseProducer = getConfig().getNoiseImpl();
+		BufferedImage distortedImage = new BufferedImage(baseImage.getWidth(),
+				baseImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
+
+		Graphics2D graphics = (Graphics2D) distortedImage.getGraphics();
+
+		RippleFilter rippleFilter = new RippleFilter();
+		rippleFilter.setWaveType(RippleFilter.SINE);
+		rippleFilter.setXAmplitude(2.6f);
+		rippleFilter.setYAmplitude(1.7f);
+		rippleFilter.setXWavelength(15);
+		rippleFilter.setYWavelength(5);
+		rippleFilter.setEdgeAction(TransformFilter.NEAREST_NEIGHBOUR);
+
+		BufferedImage effectImage = rippleFilter.filter(baseImage, null);
+		
+		graphics.drawImage(effectImage, 0, 0, null, null);
+
+		graphics.dispose();
+
+		noiseProducer.makeNoise(distortedImage, .1f, .1f, .25f, .25f);
+		noiseProducer.makeNoise(distortedImage, .1f, .25f, .5f, .9f);
+		return distortedImage;
+	}
+}

+ 128 - 0
maxkey-authentications/maxkey-authentication-captcha/src/main/java/com/google/code/kaptcha/text/impl/RandomColorWordRenderer.java

@@ -0,0 +1,128 @@
+package com.google.code.kaptcha.text.impl;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.Random;
+import com.google.code.kaptcha.text.WordRenderer;
+import com.google.code.kaptcha.util.ConfigHelper;
+import com.google.code.kaptcha.util.Configurable;
+
+/**
+ * The default implementation of {@link WordRenderer}, creates an image with a
+ * word rendered on it.
+ */
+public class RandomColorWordRenderer extends Configurable implements WordRenderer
+{
+	ConfigHelper configHelper = new ConfigHelper();
+	/**
+	 * Renders a word to an image.
+	 * 
+	 * @param word
+	 *            The word to be rendered.
+	 * @param width
+	 *            The width of the image to be created.
+	 * @param height
+	 *            The height of the image to be created.
+	 * @return The BufferedImage created from the word.
+	 */
+	public BufferedImage renderWord(String word, int width, int height)
+	{
+		int fontSize = getConfig().getTextProducerFontSize();
+		Font[] fonts = getConfig().getTextProducerFonts(fontSize);
+		Color color = getConfig().getTextProducerFontColor();
+		int charSpace = getConfig().getTextProducerCharSpace();
+		BufferedImage image = new BufferedImage(width, height,
+				BufferedImage.TYPE_INT_ARGB);
+		Graphics2D g2D = image.createGraphics();
+		g2D.setColor(color);
+
+		RenderingHints hints = new RenderingHints(
+				RenderingHints.KEY_ANTIALIASING,
+				RenderingHints.VALUE_ANTIALIAS_ON);
+		hints.add(new RenderingHints(RenderingHints.KEY_RENDERING,
+				RenderingHints.VALUE_RENDER_QUALITY));
+		g2D.setRenderingHints(hints);
+
+		FontRenderContext frc = g2D.getFontRenderContext();
+		Random random = new SecureRandom();
+
+		int startPosY = (height - fontSize) / 5 + fontSize;
+
+		char[] wordChars = word.toCharArray();
+		Font[] chosenFonts = new Font[wordChars.length];
+		int [] charWidths = new int[wordChars.length];
+		int widthNeeded = 0;
+		for (int i = 0; i < wordChars.length; i++)
+		{
+			
+			//chosenFonts[i] = new Font("Arial", Font.BOLD, fontSize);
+			//random
+			chosenFonts[i] = fonts[random.nextInt(fonts.length)];
+
+			char[] charToDraw = new char[]{
+				wordChars[i]
+			};
+			GlyphVector gv = chosenFonts[i].createGlyphVector(frc, charToDraw);
+			charWidths[i] = (int)gv.getVisualBounds().getWidth();
+			if (i > 0)
+			{
+				widthNeeded = widthNeeded + 2;
+			}
+			widthNeeded = widthNeeded + charWidths[i];
+		}
+		
+		HashMap<String,String> selectedColor =new HashMap<String,String>();
+		int startPosX = (width - widthNeeded) / 2;
+		
+		for (int i = 0; i < wordChars.length; i++)
+		{
+			String randomcolor="";
+			do {
+				randomcolor=COLOR_LIST[random.nextInt(COLOR_LIST.length)].replaceAll(" ", "");
+			}while(selectedColor.containsKey(randomcolor));
+			
+			selectedColor.put(randomcolor, randomcolor);
+			
+			color = configHelper.getColor(randomcolor, randomcolor, Color.LIGHT_GRAY);
+			g2D.setColor(color);
+			
+			g2D.setFont(chosenFonts[i]);
+			
+			char[] charToDraw = new char[] {
+				wordChars[i]
+			};
+			
+			//System.out.println(charToDraw[0] +" - "+chosenFonts[i]);
+			g2D.drawChars(charToDraw, 0, charToDraw.length, startPosX, startPosY);
+			startPosX = startPosX + (int) charWidths[i] + charSpace;
+		}
+		
+		return image;
+	}
+	
+	static String [] COLOR_LIST = {
+			//"255, 255, 255",//white
+			//"192, 192, 192",//silver
+			//"128, 128, 128",//gray
+			"0, 0, 0",//black
+			"255, 0, 0",//red
+			"128, 0, 0",//maroon
+			"255, 255, 0",//yellow
+			"128, 128, 0",//olive
+			"0, 255, 0",//lime
+			"0, 128, 0",//green
+			"0, 255, 255",//aqua
+			"0, 128, 128",//teal
+			"0, 0, 255",//blue
+			"0, 0, 128",//navy
+			"255, 0, 255",//fuchsia
+			"128, 0, 128"//purple
+	};
+}

+ 13 - 0
maxkey-authentications/maxkey-authentication-captcha/src/main/resources/kaptcha_c.properties

@@ -0,0 +1,13 @@
+kaptcha.image.width=80
+kaptcha.image.height=25
+kaptcha.border=no
+#kaptcha.obscurificator.impl=com.google.code.kaptcha.impl.ShadowGimpy
+kaptcha.obscurificator.impl=com.google.code.kaptcha.impl.Ripple
+kaptcha.textproducer.font.size=23
+kaptcha.textproducer.char.string=0123456789
+kaptcha.textproducer.char.length=4
+kaptcha.textproducer.char.space=3
+#kaptcha.noise.impl=com.google.code.kaptcha.impl.DefaultNoise
+kaptcha.noise.impl=com.google.code.kaptcha.impl.LightNoise
+#kaptcha.noise.color=white
+kaptcha.word.impl=com.google.code.kaptcha.text.impl.RandomColorWordRenderer

+ 27 - 0
maxkey-gataway/src/main/java/org/gateway/filter/AuthAndLogFilter.java

@@ -0,0 +1,27 @@
+package org.gateway.filter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+@Component
+public class AuthAndLogFilter implements GlobalFilter, Ordered {
+
+	private final Logger logger = LoggerFactory.getLogger(getClass());
+
+	@Override
+	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+		return chain.filter(exchange.mutate().build());
+	}
+
+	@Override
+	public int getOrder() {
+	    logger.trace(" -20");
+		return -20;
+	}
+}

+ 125 - 0
maxkey-gataway/src/main/java/org/gateway/route/NacosDynamicRouteService.java

@@ -0,0 +1,125 @@
+/*
+package org.gateway.route;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.PropertyKeyConst;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.Listener;
+import com.alibaba.nacos.api.exception.NacosException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
+import org.springframework.cloud.gateway.route.RouteDefinition;
+import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.ApplicationEventPublisherAware;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import javax.annotation.PostConstruct;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+
+@Component
+public class NacosDynamicRouteService implements ApplicationEventPublisherAware {
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    private String dataId = "alibaba-gateway-router";
+ 
+    private String group = "DEFAULT_GROUP";
+ 
+    @Value("${spring.cloud.nacos.config.server-addr}")
+    private String serverAddr;
+
+    @Value("${spring.cloud.nacos.config.namespace}")
+    private String namespace;
+ 
+    @Autowired
+    private RouteDefinitionWriter routeDefinitionWriter;
+ 
+    private ApplicationEventPublisher applicationEventPublisher;
+ 
+    private static final List<String> ROUTE_LIST = new ArrayList<>();
+ 
+    @PostConstruct
+    public void dynamicRouteByNacosListener() {
+        try {
+            logger.info("serverAddr:{}",serverAddr);
+            logger.info("namespace:{}",namespace);
+            logger.info("dataId:{}",dataId);
+            logger.info("group:{}",group);
+            Properties properties = new Properties();
+            properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
+            properties.put(PropertyKeyConst.NAMESPACE, namespace);
+
+            ConfigService configService = NacosFactory.createConfigService(properties);
+            configService.getConfig(dataId, group, 5000);
+
+            // 程序首次启动, 并加载初始化路由配置
+            String initConfigInfo = configService.getConfig(dataId, group, 5000);
+            addAndPublishBatchRoute(initConfigInfo);
+            publish();
+            configService.addListener(dataId, group, new Listener() {
+                @Override
+                public void receiveConfigInfo(String configInfo) {
+                    clearRoute();
+                    try {
+                        List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class);
+                        for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
+                            logger.info("routeDefinition:{}",routeDefinition);
+                            addRoute(routeDefinition);
+                        }
+                        publish();
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+                @Override
+                public Executor getExecutor() {
+                    return null;
+                }
+            });
+        } catch (NacosException e) {
+            logger.error("error:{}",e);
+        }
+    }
+ 
+    private void clearRoute() {
+        for(String id : ROUTE_LIST) {
+            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
+        }
+        ROUTE_LIST.clear();
+    }
+
+    private void addAndPublishBatchRoute(String initConfigInfo){
+        List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(initConfigInfo, RouteDefinition.class);
+        for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
+            logger.info("init routeDefinition:{}",routeDefinition);
+            addRoute(routeDefinition);
+        }
+    }
+    private void addRoute(RouteDefinition definition) {
+        try {
+            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
+            ROUTE_LIST.add(definition.getId());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+ 
+    private void publish() {
+        this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));
+    }
+ 
+    @Override
+    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
+        this.applicationEventPublisher = applicationEventPublisher;
+    }
+}
+*/