架构

spring项目结构设计-验证码工具类

2020-05-13  本文已影响0人  jinelei

注意:这里是依赖awt的

object VerifyCodeUtils {
    //使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符
    const val VERIFY_CODES = "0123456789"
    private val random: Random = Random()
    /**
     * 使用指定源生成验证码
     *
     * @param verifySize 验证码长度
     * @param sources    验证码字符源
     * @return
     */
    /**
     * 使用系统默认字符源生成验证码
     *
     * @param verifySize 验证码长度
     * @return
     */
    @JvmOverloads
    fun generateVerifyCode(verifySize: Int, sourceCode: String? = VERIFY_CODES): String {
        var sources = sourceCode
        if (sources == null || sources.length == 0) {
            sources = VERIFY_CODES
        }
        val codesLen = sources.length
        val rand = Random(System.currentTimeMillis())
        val verifyCode = StringBuilder(verifySize)
        for (i in 0 until verifySize) {
            verifyCode.append(sources[rand.nextInt(codesLen - 1)])
        }
        return verifyCode.toString()
    }

    /**
     * 生成随机验证码文件,并返回验证码值
     *
     * @param w
     * @param h
     * @param outputFile
     * @param verifySize
     * @return
     * @throws IOException
     */
    @Throws(IOException::class)
    fun outputVerifyImage(w: Int, h: Int, outputFile: File?, verifySize: Int): String {
        val verifyCode = generateVerifyCode(verifySize)
        outputImage(w, h, outputFile, verifyCode)
        return verifyCode
    }

    /**
     * 输出随机验证码图片流,并返回验证码值
     *
     * @param w
     * @param h
     * @param os
     * @param verifySize
     * @return
     * @throws IOException
     */
    @Throws(IOException::class)
    fun outputVerifyImage(w: Int, h: Int, os: OutputStream?, verifySize: Int): String {
        val verifyCode = generateVerifyCode(verifySize)
        outputImage(w, h, os, verifyCode)
        return verifyCode
    }

    /**
     * 生成指定验证码图像文件
     *
     * @param w
     * @param h
     * @param outputFile
     * @param code
     * @throws IOException
     */
    @Throws(IOException::class)
    fun outputImage(w: Int, h: Int, outputFile: File?, code: String?) {
        if (outputFile == null) {
            return
        }
        val dir: File = outputFile.getParentFile()
        if (!dir.exists()) {
            dir.mkdirs()
        }
        try {
            outputFile.createNewFile()
            val fos = FileOutputStream(outputFile)
            outputImage(w, h, fos, code!!)
            fos.close()
        } catch (e: IOException) {
            throw e
        }
    }

    /**
     * 输出指定验证码图片流
     *
     * @param w
     * @param h
     * @param os
     * @param code
     * @throws IOException
     */
    @Throws(IOException::class)
    fun outputImage(w: Int, h: Int, os: OutputStream?, code: String) {
        val verifySize = code.length
        val image = BufferedImage(w, h, BufferedImage.TYPE_INT_RGB)
        val rand = Random()
        val g2 = image.createGraphics()
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
        val colors: Array<Color?> = arrayOfNulls<Color>(5)
        val colorSpaces: Array<Color> = arrayOf<Color>(Color.WHITE, Color.CYAN,
                Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
                Color.PINK, Color.YELLOW)
        val fractions = FloatArray(colors.size)
        for (i in colors.indices) {
            colors[i] = colorSpaces[rand.nextInt(colorSpaces.size)]
            fractions[i] = rand.nextFloat()
        }
        Arrays.sort(fractions)
        g2.color = Color.GRAY // 设置边框色
        g2.fillRect(0, 0, w, h)
        val c: Color = getRandColor(200, 250)
        g2.color = c // 设置背景色
        g2.fillRect(0, 2, w, h - 4)
        //绘制干扰线
        val random = Random()
        g2.color = getRandColor(160, 200) // 设置线条的颜色
        for (i in 0..19) {
            val x: Int = random.nextInt(w - 1)
            val y: Int = random.nextInt(h - 1)
            val xl: Int = random.nextInt(6) + 1
            val yl: Int = random.nextInt(12) + 1
            g2.drawLine(x, y, x + xl + 40, y + yl + 20)
        }
        // 添加噪点
        val yawpRate = 0.05f // 噪声率
        val area = (yawpRate * w * h).toInt()
        for (i in 0 until area) {
            val x: Int = random.nextInt(w)
            val y: Int = random.nextInt(h)
            val rgb = randomIntColor
            image.setRGB(x, y, rgb)
        }
        shear(g2, w, h, c) // 使图片扭曲
        g2.color = getRandColor(100, 160)
        val fontSize = h - 4
        val font = Font("Algerian", Font.ITALIC, fontSize)
        g2.font = font
        val chars = code.toCharArray()
        for (i in 0 until verifySize) {
            val affine = AffineTransform()
            affine.setToRotation(Math.PI / 4 * rand.nextDouble() * if (rand.nextBoolean()) 1 else -1, w / verifySize * i + fontSize / 2.toDouble(), h / 2.toDouble())
            g2.transform = affine
            g2.drawChars(chars, i, 1, (w - 10) / verifySize * i + 5, h / 2 + fontSize / 2 - 10)
        }
        g2.dispose()
        ImageIO.write(image, "jpg", os)
    }

    private fun getRandColor(frontColor: Int, backgroundColor: Int): Color {
        var fc = frontColor
        var bc = backgroundColor
        if (fc > 255) fc = 255
        if (bc > 255) bc = 255
        val r: Int = fc + random.nextInt(bc - fc)
        val g: Int = fc + random.nextInt(bc - fc)
        val b: Int = fc + random.nextInt(bc - fc)
        return Color(r, g, b)
    }

    private val randomIntColor: Int
        get() {
            val rgb = randomRgb
            var color = 0
            for (c in rgb) {
                color = color shl 8
                color = color or c
            }
            return color
        }

    private val randomRgb: IntArray
        get() {
            val rgb = IntArray(3)
            for (i in 0..2) {
                rgb[i] = random.nextInt(255)
            }
            return rgb
        }

    private fun shear(g: Graphics, w1: Int, h1: Int, color: Color) {
        shearX(g, w1, h1, color)
        shearY(g, w1, h1, color)
    }

    private fun shearX(g: Graphics, w1: Int, h1: Int, color: Color) {
        val period: Int = random.nextInt(2)
        val borderGap = true
        val frames = 1
        val phase: Int = random.nextInt(2)
        for (i in 0 until h1) {
            val d = ((period shr 1).toDouble()
                    * Math.sin(i.toDouble() / period.toDouble()
                    + 6.2831853071795862 * phase.toDouble()
                    / frames.toDouble()))
            g.copyArea(0, i, w1, 1, d.toInt(), 0)
            if (borderGap) {
                g.setColor(color)
                g.drawLine(d.toInt(), i, 0, i)
                g.drawLine(d.toInt() + w1, i, w1, i)
            }
        }
    }

    private fun shearY(g: Graphics, w1: Int, h1: Int, color: Color) {
        val period: Int = random.nextInt(40) + 10 // 50;
        val borderGap = true
        val frames = 20
        val phase = 7
        for (i in 0 until w1) {
            val d = ((period shr 1).toDouble()
                    * Math.sin(i.toDouble() / period.toDouble()
                    + 6.2831853071795862 * phase.toDouble()
                    / frames.toDouble()))
            g.copyArea(i, 0, 1, h1, 0, d.toInt())
            if (borderGap) {
                g.setColor(color)
                g.drawLine(i, d.toInt(), i, 0)
                g.drawLine(i, d.toInt() + h1, i, h1)
            }
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读