diff --git a/maxkey-authentications/maxkey-authentication-captcha/src/main/java/com/google/code/kaptcha/impl/LightNoise.java b/maxkey-authentications/maxkey-authentication-captcha/src/main/java/com/google/code/kaptcha/impl/LightNoise.java new file mode 100644 index 00000000..f9f236c5 --- /dev/null +++ b/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(); + } +} \ No newline at end of file diff --git a/maxkey-authentications/maxkey-authentication-captcha/src/main/java/com/google/code/kaptcha/impl/Ripple.java b/maxkey-authentications/maxkey-authentication-captcha/src/main/java/com/google/code/kaptcha/impl/Ripple.java new file mode 100644 index 00000000..b0a2c429 --- /dev/null +++ b/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; + } +} diff --git a/maxkey-authentications/maxkey-authentication-captcha/src/main/java/com/google/code/kaptcha/text/impl/RandomColorWordRenderer.java b/maxkey-authentications/maxkey-authentication-captcha/src/main/java/com/google/code/kaptcha/text/impl/RandomColorWordRenderer.java new file mode 100644 index 00000000..050770cc --- /dev/null +++ b/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 selectedColor =new HashMap(); + 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 + }; +} diff --git a/maxkey-authentications/maxkey-authentication-captcha/src/main/resources/kaptcha_c.properties b/maxkey-authentications/maxkey-authentication-captcha/src/main/resources/kaptcha_c.properties new file mode 100644 index 00000000..5c49aec9 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/maxkey-gataway/src/main/java/org/gateway/filter/AuthAndLogFilter.java b/maxkey-gataway/src/main/java/org/gateway/filter/AuthAndLogFilter.java new file mode 100644 index 00000000..d2094bd2 --- /dev/null +++ b/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 filter(ServerWebExchange exchange, GatewayFilterChain chain) { + return chain.filter(exchange.mutate().build()); + } + + @Override + public int getOrder() { + logger.trace(" -20"); + return -20; + } +} diff --git a/maxkey-gataway/src/main/java/org/gateway/route/NacosDynamicRouteService.java b/maxkey-gataway/src/main/java/org/gateway/route/NacosDynamicRouteService.java new file mode 100644 index 00000000..5b799d8c --- /dev/null +++ b/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 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 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 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; + } +} +*/