├── .gitignore ├── README.md ├── kaptcha-spring-boot-starter-redis-example ├── .gitignore ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ryanbing │ │ │ ├── KaptchaSpringBootStarterRedisExampleApplication.java │ │ │ └── web │ │ │ └── RedisDemoController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── ryanbing │ └── KaptchaSpringBootStarterRedisExampleApplicationTests.java ├── kaptcha-spring-boot-starter-session-example ├── .gitignore ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ryanbing │ │ │ ├── KaptchaSpringBootStarterSessionExampleApplication.java │ │ │ └── web │ │ │ └── SessionDemoController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── ryanbing │ └── KaptchaSpringBootStarterSessionExampleApplicationTests.java ├── kaptcha-spring-boot-starter ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── ryanbing │ │ └── kaptcha │ │ └── spring │ │ └── boot │ │ ├── JedisUtil.java │ │ ├── KaptchaAdapter.java │ │ ├── KaptchaAutoConfiguration.java │ │ ├── KaptchaProperties.java │ │ ├── RedisKaptcha.java │ │ ├── SessionKaptcha.java │ │ └── SessionUtil.java │ └── resources │ └── META-INF │ └── spring.factories └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | *.class 5 | 6 | .idea 7 | *.iml 8 | 9 | # Log file 10 | *.log 11 | 12 | # BlueJ files 13 | *.ctxt 14 | 15 | # Mobile Tools for Java (J2ME) 16 | .mtj.tmp/ 17 | 18 | # Package Files # 19 | *.jar 20 | .mvn 21 | *.war 22 | *.nar 23 | *.ear 24 | *.zip 25 | *.tar.gz 26 | *.rar 27 | 28 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 29 | hs_err_pid* 30 | */target/ 31 | *.DS_Store 32 | .vscode 33 | /.vscode/ 34 | 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kaptcha Spring boot starter 2 | 3 | Very simple way to use [Kaptcha](http://code.google.com/p/kaptcha/).and 4 | you can use session and redis to store captcha information. 5 | ## Installation and Getting Started 6 | 7 | 8 | ```xml 9 | 10 | com.ryanbing 11 | kaptcha-spring-boot-starter 12 | 1.0.1.RELEASE 13 | 14 | ``` 15 | 16 | ### Session Sample 17 | 18 | *application.properties* 19 | 20 | ``` 21 | spring.kaptcha.store=session 22 | ``` 23 | 24 | *sample:* 25 | 26 | ```java 27 | @RestController 28 | @RequestMapping(value = "/sessioin") 29 | public class SessionDemoController { 30 | @Autowired 31 | private SessionKaptcha sessionKaptcha; 32 | 33 | @RequestMapping(value = "/captcha",method = {RequestMethod.POST, RequestMethod.GET}) 34 | public void getCap(HttpServletRequest request, HttpServletResponse response) throws IOException { 35 | sessionKaptcha.setCaptcha(request, response); 36 | } 37 | 38 | @RequestMapping(value = "/valid",method = {RequestMethod.POST, RequestMethod.GET}) 39 | public boolean isValid(HttpServletRequest request, String captcha) { 40 | return sessionKaptcha.validCaptcha(request,captcha); 41 | } 42 | 43 | } 44 | ``` 45 | 46 | ### Redis Sample 47 | 48 | *application.properties* 49 | 50 | ``` 51 | spring.kaptcha.store=redis 52 | spring.kaptcha.redis=127.0.0.1:6379 53 | ``` 54 | 55 | *sample:* 56 | 57 | ```java 58 | @RestController 59 | @RequestMapping(value = "/redis") 60 | public class RedisDemoController { 61 | @Autowired 62 | private RedisKaptcha redisKaptcha; 63 | 64 | @RequestMapping(value = "/captcha",method = {RequestMethod.POST, RequestMethod.GET}) 65 | public void getCap(HttpServletRequest request, HttpServletResponse response) throws IOException { 66 | redisKaptcha.setCaptcha(request, response); 67 | } 68 | 69 | @RequestMapping(value = "/valid",method = {RequestMethod.POST, RequestMethod.GET}) 70 | public boolean isValid(HttpServletRequest request, String captcha) { 71 | return redisKaptcha.validCaptcha(request,captcha); 72 | } 73 | } 74 | ``` 75 | 76 | ## application.yml 77 | 78 | ```yml 79 | spring: 80 | kaptcha: 81 | store: session| redis 82 | redis: 127.0.0.1:6379,127.0.0.1:6378 83 | timeout: 60000 84 | properties: 85 | kaptcha.border: yes 86 | kaptcha.border.color: black 87 | kaptcha.border.thickness: 1 88 | kaptcha.image.width: 200 89 | kaptcha.image.height: 50 90 | kaptcha.producer.impl: com.google.code.kaptcha.impl.DefaultKaptcha 91 | kaptcha.textproducer.impl: com.google.code.kaptcha.text.impl.DefaultTextCreator 92 | kaptcha.textproducer.char.string: abcde2345678gfynmnpwx 93 | kaptcha.textproducer.char.length: 5 94 | kaptcha.textproducer.font.names: Arial, Courier 95 | kaptcha.textproducer.font.size: 40px 96 | kaptcha.textproducer.font.color: black 97 | kaptcha.textproducer.char.space: 2 98 | kaptcha.noise.impl: com.google.code.kaptcha.impl.DefaultNoise 99 | kaptcha.noise.color: black 100 | kaptcha.obscurificator.impl: com.google.code.kaptcha.impl.WaterRipple 101 | kaptcha.background.impl: com.google.code.kaptcha.impl.DefaultBackground 102 | kaptcha.background.clear.from: light grey 103 | kaptcha.background.clear.to: white 104 | kaptcha.word.impl: com.google.code.kaptcha.text.impl.DefaultWordRenderer 105 | ``` 106 | 107 | 108 | ## project 109 | 110 | [Single Sign On](https://github.com/ycvbcvfu/y-sso) 111 | 112 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-redis-example/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-redis-example/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-redis-example/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-redis-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.ryanbing 7 | kaptcha-spring-boot-starter-redis-example 8 | 1.0.1.RELEASE 9 | jar 10 | 11 | kaptcha-spring-boot-starter-redis-example 12 | redis demo project for kaptcha-spring-boot-starter 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.5.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-test 36 | test 37 | 38 | 39 | 40 | com.ryanbing 41 | kaptcha-spring-boot-starter 42 | 1.0.1.RELEASE 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-maven-plugin 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-redis-example/src/main/java/com/ryanbing/KaptchaSpringBootStarterRedisExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class KaptchaSpringBootStarterRedisExampleApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(KaptchaSpringBootStarterRedisExampleApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-redis-example/src/main/java/com/ryanbing/web/RedisDemoController.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing.web; 2 | 3 | import com.ryanbing.kaptcha.spring.boot.RedisKaptcha; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RequestMethod; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | 13 | /** 14 | * @author ryanbing 15 | **/ 16 | @RestController 17 | @RequestMapping(value = "/redis") 18 | public class RedisDemoController { 19 | @Autowired 20 | private RedisKaptcha redisKaptcha; 21 | 22 | @RequestMapping(value = "/captcha",method = {RequestMethod.POST, RequestMethod.GET}) 23 | public void getCap(HttpServletRequest request, HttpServletResponse response) throws IOException { 24 | redisKaptcha.setCaptcha(request, response); 25 | } 26 | 27 | @RequestMapping(value = "/valid",method = {RequestMethod.POST, RequestMethod.GET}) 28 | public boolean isValid(HttpServletRequest request, String captcha) { 29 | return redisKaptcha.validCaptcha(request,captcha); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-redis-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.kaptcha.store=redis 2 | spring.kaptcha.redis=127.0.0.1:6379 -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-redis-example/src/test/java/com/ryanbing/KaptchaSpringBootStarterRedisExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class KaptchaSpringBootStarterRedisExampleApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-session-example/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-session-example/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-session-example/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-session-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.ryanbing 7 | kaptcha-spring-boot-starter-session-example 8 | 1.0.1.RELEASE 9 | jar 10 | 11 | kaptcha-spring-boot-starter-session-example 12 | session demo project for kaptcha-spring-boot-starter 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.5.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-test 36 | test 37 | 38 | 39 | 40 | com.ryanbing 41 | kaptcha-spring-boot-starter 42 | 1.0.1.RELEASE 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-maven-plugin 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-session-example/src/main/java/com/ryanbing/KaptchaSpringBootStarterSessionExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class KaptchaSpringBootStarterSessionExampleApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(KaptchaSpringBootStarterSessionExampleApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-session-example/src/main/java/com/ryanbing/web/SessionDemoController.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing.web; 2 | 3 | import com.ryanbing.kaptcha.spring.boot.SessionKaptcha; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RequestMethod; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | 13 | /** 14 | * @author ryanbing 15 | **/ 16 | @RestController 17 | @RequestMapping(value = "/sessioin") 18 | public class SessionDemoController { 19 | @Autowired 20 | private SessionKaptcha sessionKaptcha; 21 | 22 | @RequestMapping(value = "/captcha",method = {RequestMethod.POST, RequestMethod.GET}) 23 | public void getCap(HttpServletRequest request, HttpServletResponse response) throws IOException { 24 | sessionKaptcha.setCaptcha(request, response); 25 | } 26 | 27 | @RequestMapping(value = "/valid",method = {RequestMethod.POST, RequestMethod.GET}) 28 | public boolean isValid(HttpServletRequest request, String captcha) { 29 | return sessionKaptcha.validCaptcha(request,captcha); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-session-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.kaptcha.store=session -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter-session-example/src/test/java/com/ryanbing/KaptchaSpringBootStarterSessionExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class KaptchaSpringBootStarterSessionExampleApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | com.ryanbing 9 | kaptcha-spring-boot-starter 10 | 1.0.1.RELEASE 11 | kaptcha spring boot starter 12 | jar 13 | 14 | https://github.com/ycvbcvfu/captcha-spring-boot-starter 15 | kaptcha-spring-boot-starter 16 | 17 | 18 | 19 | Apache License, Version 2.0 20 | http://www.apache.org/licenses/LICENSE-2.0 21 | repo 22 | 23 | 24 | 25 | 26 | scm:git:https://github.com/ycvbcvfu/captcha-spring-boot-starter 27 | scm:git:git@github.com:ycvbcvfu/captcha-spring-boot-starter 28 | https://github.com/ycvbcvfu/captcha-spring-boot-starter 29 | 1.0.1.RELEASE 30 | 31 | 32 | GitHub Issues 33 | https://github.com/ycvbcvfu/captcha-spring-boot-starter/issues 34 | 35 | 36 | 37 | 38 | 39 | ryanbing 40 | ycvbcvfu@qq.com 41 | +8 42 | 43 | 44 | 45 | 46 | 47 | UTF-8 48 | 1.8 49 | 2.9.0 50 | 1.7.25 51 | 2.3.2 52 | 53 | 54 | 2.0.4.RELEASE 55 | 56 | 57 | 3.5.1 58 | 2.2.1 59 | 2.9.1 60 | 1.6 61 | 62 | 63 | 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-configuration-processor 69 | true 70 | 71 | 72 | 73 | 74 | org.springframework.boot 75 | spring-boot-autoconfigure 76 | 77 | 78 | 79 | com.github.penggle 80 | kaptcha 81 | ${kaptcha.version} 82 | 83 | 84 | 85 | org.slf4j 86 | slf4j-api 87 | ${slf4j-api.version} 88 | 89 | 90 | 91 | redis.clients 92 | jedis 93 | ${jedis.version} 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | org.springframework.boot 102 | spring-boot-dependencies 103 | ${spring-boot.version} 104 | pom 105 | import 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | ryanbing 114 | https://oss.sonatype.org/content/repositories/snapshots 115 | 116 | 117 | ryanbing 118 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | org.apache.maven.plugins 127 | maven-compiler-plugin 128 | ${version.compiler-plugin} 129 | 130 | ${java.version} 131 | ${java.version} 132 | ${java.version} 133 | 134 | 135 | 136 | org.apache.maven.plugins 137 | maven-source-plugin 138 | ${version.source-plugin} 139 | 140 | 141 | package 142 | 143 | jar-no-fork 144 | 145 | 146 | 147 | 148 | 149 | org.apache.maven.plugins 150 | maven-javadoc-plugin 151 | ${version.javadoc-plugin} 152 | 153 | 154 | package 155 | 156 | jar 157 | 158 | 159 | 160 | 161 | 162 | org.apache.maven.plugins 163 | maven-gpg-plugin 164 | 1.6 165 | 166 | 167 | sign-artifacts 168 | verify 169 | 170 | sign 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter/src/main/java/com/ryanbing/kaptcha/spring/boot/JedisUtil.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing.kaptcha.spring.boot; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import redis.clients.jedis.JedisPoolConfig; 6 | import redis.clients.jedis.JedisShardInfo; 7 | import redis.clients.jedis.ShardedJedis; 8 | import redis.clients.jedis.ShardedJedisPool; 9 | 10 | import java.io.*; 11 | import java.util.LinkedList; 12 | import java.util.List; 13 | import java.util.concurrent.TimeUnit; 14 | import java.util.concurrent.locks.ReentrantLock; 15 | 16 | 17 | public class JedisUtil { 18 | private static Logger logger = LoggerFactory.getLogger(JedisUtil.class); 19 | 20 | private static final int DEFAULT_EXPIRE_TIME = 60; 21 | private static String address; 22 | private static ShardedJedisPool shardedJedisPool; 23 | private static ReentrantLock INSTANCE_INIT_LOCL = new ReentrantLock(false); 24 | 25 | public static void init(String address) { 26 | JedisUtil.address = address; 27 | } 28 | 29 | 30 | private static ShardedJedis getInstance() { 31 | if (shardedJedisPool == null) { 32 | try { 33 | if (INSTANCE_INIT_LOCL.tryLock(2, TimeUnit.SECONDS)) { 34 | 35 | try { 36 | 37 | if (shardedJedisPool == null) { 38 | JedisPoolConfig config = new JedisPoolConfig(); 39 | config.setMaxTotal(200); 40 | config.setMaxIdle(50); 41 | config.setMinIdle(10); 42 | config.setMaxWaitMillis(10000); 43 | config.setTestOnBorrow(true); 44 | config.setTestOnReturn(true); 45 | config.setTestWhileIdle(true); 46 | config.setTimeBetweenEvictionRunsMillis(30000); 47 | config.setNumTestsPerEvictionRun(10); 48 | config.setMinEvictableIdleTimeMillis(60000); 49 | 50 | List jedisShardInfos = new LinkedList(); 51 | 52 | String[] addressArr = address.split(","); 53 | for (String anAddressArr : addressArr) { 54 | String[] addressInfo = anAddressArr.split(":"); 55 | String host = addressInfo[0]; 56 | int port = Integer.valueOf(addressInfo[1]); 57 | JedisShardInfo jedisShardInfo = new JedisShardInfo(host, port, 10000); 58 | jedisShardInfos.add(jedisShardInfo); 59 | } 60 | shardedJedisPool = new ShardedJedisPool(config, jedisShardInfos); 61 | } 62 | 63 | } finally { 64 | INSTANCE_INIT_LOCL.unlock(); 65 | } 66 | } 67 | 68 | } catch (InterruptedException e) { 69 | logger.error(e.getMessage(), e); 70 | } 71 | } 72 | 73 | if (shardedJedisPool == null) { 74 | throw new NullPointerException(" JedisUtil ShardedJedisPool is null."); 75 | } 76 | 77 | return shardedJedisPool.getResource(); 78 | } 79 | 80 | // ------------------------ serialize and unserialize ------------------------ 81 | 82 | private static byte[] serialize(Object object) { 83 | ObjectOutputStream oos = null; 84 | ByteArrayOutputStream baos = null; 85 | try { 86 | // 序列化 87 | baos = new ByteArrayOutputStream(); 88 | oos = new ObjectOutputStream(baos); 89 | oos.writeObject(object); 90 | byte[] bytes = baos.toByteArray(); 91 | return bytes; 92 | } catch (Exception e) { 93 | logger.error("{}", e); 94 | } finally { 95 | try { 96 | oos.close(); 97 | baos.close(); 98 | } catch (IOException e) { 99 | logger.error("{}", e); 100 | } 101 | } 102 | return null; 103 | } 104 | 105 | private static Object unserialize(byte[] bytes) { 106 | ByteArrayInputStream bais = null; 107 | try { 108 | // 反序列化 109 | bais = new ByteArrayInputStream(bytes); 110 | ObjectInputStream ois = new ObjectInputStream(bais); 111 | return ois.readObject(); 112 | } catch (Exception e) { 113 | logger.error("{}", e); 114 | } finally { 115 | try { 116 | bais.close(); 117 | } catch (IOException e) { 118 | logger.error("{}", e); 119 | } 120 | } 121 | return null; 122 | } 123 | 124 | // ------------------------ jedis util ------------------------ 125 | 126 | public static String setStringValue(String key, String value, int seconds) { 127 | String result = null; 128 | ShardedJedis client = getInstance(); 129 | try { 130 | result = client.setex(key, seconds, value); 131 | } catch (Exception e) { 132 | logger.info("{}", e); 133 | } finally { 134 | client.close(); 135 | } 136 | return result; 137 | } 138 | 139 | public static String setStringValue(String key, String value) { 140 | return setStringValue(key, value, DEFAULT_EXPIRE_TIME); 141 | } 142 | 143 | 144 | public static String setObjectValue(String key, Object obj, int seconds) { 145 | String result = null; 146 | ShardedJedis client = getInstance(); 147 | try { 148 | result = client.setex(key.getBytes(), seconds, serialize(obj)); 149 | } catch (Exception e) { 150 | logger.info("{}", e); 151 | } finally { 152 | client.close(); 153 | } 154 | return result; 155 | } 156 | 157 | 158 | public static String setObjectValue(String key, Object obj) { 159 | return setObjectValue(key, obj, DEFAULT_EXPIRE_TIME); 160 | } 161 | 162 | 163 | public static String getStringValue(String key) { 164 | String value = null; 165 | ShardedJedis client = getInstance(); 166 | try { 167 | value = client.get(key); 168 | } catch (Exception e) { 169 | logger.info("", e); 170 | } finally { 171 | client.close(); 172 | } 173 | return value; 174 | } 175 | 176 | 177 | public static Object getObjectValue(String key) { 178 | Object obj = null; 179 | ShardedJedis client = getInstance(); 180 | try { 181 | byte[] bytes = client.get(key.getBytes()); 182 | if (bytes != null && bytes.length > 0) { 183 | obj = unserialize(bytes); 184 | } 185 | } catch (Exception e) { 186 | logger.info("", e); 187 | } finally { 188 | client.close(); 189 | } 190 | return obj; 191 | } 192 | 193 | public static Long del(String key) { 194 | Long result = null; 195 | ShardedJedis client = getInstance(); 196 | try { 197 | result = client.del(key); 198 | } catch (Exception e) { 199 | logger.info("{}", e); 200 | } finally { 201 | client.close(); 202 | } 203 | return result; 204 | } 205 | 206 | public static Long incrBy(String key, int i) { 207 | Long result = null; 208 | ShardedJedis client = getInstance(); 209 | try { 210 | result = client.incrBy(key, i); 211 | } catch (Exception e) { 212 | logger.info("{}", e); 213 | } finally { 214 | client.close(); 215 | } 216 | return result; 217 | } 218 | 219 | public static Long decrBy(String key, int i) { 220 | Long result = null; 221 | ShardedJedis client = getInstance(); 222 | try { 223 | result = client.incrBy(key, -i); 224 | } catch (Exception e) { 225 | logger.info("{}", e); 226 | } finally { 227 | client.close(); 228 | } 229 | return result; 230 | } 231 | 232 | 233 | public static boolean exists(String key) { 234 | Boolean result = null; 235 | ShardedJedis client = getInstance(); 236 | try { 237 | result = client.exists(key); 238 | } catch (Exception e) { 239 | logger.info("{}", e); 240 | } finally { 241 | client.close(); 242 | } 243 | return result; 244 | } 245 | 246 | 247 | public static long expire(String key, int seconds) { 248 | Long result = null; 249 | ShardedJedis client = getInstance(); 250 | try { 251 | result = client.expire(key, seconds); 252 | } catch (Exception e) { 253 | logger.info("{}", e); 254 | } finally { 255 | client.close(); 256 | } 257 | return result; 258 | } 259 | 260 | 261 | public static long expireAt(String key, long unixTime) { 262 | Long result = null; 263 | ShardedJedis client = getInstance(); 264 | try { 265 | result = client.expireAt(key, unixTime); 266 | } catch (Exception e) { 267 | logger.info("{}", e); 268 | } finally { 269 | client.close(); 270 | } 271 | return result; 272 | } 273 | 274 | 275 | } 276 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter/src/main/java/com/ryanbing/kaptcha/spring/boot/KaptchaAdapter.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing.kaptcha.spring.boot; 2 | 3 | import com.google.code.kaptcha.Producer; 4 | import com.google.code.kaptcha.util.Config; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | import java.security.NoSuchAlgorithmException; 10 | 11 | /** 12 | * Adapter for kaptcha 13 | * 14 | * @author ryanbing 15 | **/ 16 | interface KaptchaAdapter { 17 | 18 | /** 19 | * default timeout value is 60 seconds. 20 | */ 21 | long DEFAULT_TIME_OUT = 60 * 1000; 22 | String DEFAULT_KEY_VALUE = "kaptcha.key"; 23 | String DEFAULT_KEY_DATE_VALUE = "kaptcha.datekey"; 24 | 25 | 26 | /** 27 | * init configuration default properties 28 | */ 29 | void init(); 30 | 31 | /** 32 | * @param config set configuration values, default from properties 33 | */ 34 | void init(Config config, long timeout); 35 | 36 | 37 | /** 38 | * @param keyValue captcha's key value at store 39 | * @param keyDateValue set captcha time key at store 40 | * @param timeout timeout that someone enter their captcha 41 | */ 42 | void init(String keyValue, String keyDateValue, long timeout); 43 | 44 | 45 | void init(Producer producer, String keyValue, String keyDateValue, long timeout); 46 | 47 | /** 48 | * set captcha for response 49 | * 50 | * @param request request 51 | * @param response response 52 | */ 53 | void setCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException, NoSuchAlgorithmException; 54 | 55 | 56 | /** 57 | * set captcha for response 58 | * 59 | * @param request request 60 | * @param response response 61 | * @param captchaText captcha 62 | */ 63 | void setCaptcha(HttpServletRequest request, HttpServletResponse response, String captchaText) throws IOException; 64 | 65 | void setCaptcha(HttpServletRequest req, HttpServletResponse resp, String keyValue, String keyDateValue) throws IOException; 66 | 67 | void setCaptcha(HttpServletRequest req, HttpServletResponse resp, String keyValue, String keyDateValue, String captchaText) throws IOException; 68 | 69 | 70 | /** 71 | * valid captcha when someone enter their captcha 72 | * 73 | * @param request request 74 | * @param captcha valid captcha 75 | * @return 76 | */ 77 | boolean validCaptcha(HttpServletRequest request, String captcha); 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter/src/main/java/com/ryanbing/kaptcha/spring/boot/KaptchaAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing.kaptcha.spring.boot; 2 | 3 | import com.google.code.kaptcha.impl.DefaultKaptcha; 4 | import com.google.code.kaptcha.util.Config; 5 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 6 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 7 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | /** 12 | * KaptchaAutoConfiguration 13 | * 14 | * @author ryanbing 15 | **/ 16 | 17 | @Configuration 18 | @EnableConfigurationProperties(value = KaptchaProperties.class) 19 | public class KaptchaAutoConfiguration { 20 | 21 | 22 | @Bean 23 | @ConditionalOnMissingBean 24 | @ConditionalOnProperty(prefix = "spring.kaptcha", name = "store", havingValue = "session") 25 | public SessionKaptcha sessionKaptcha(KaptchaProperties kaptchaProperties) { 26 | long timeout = kaptchaProperties.getTimeout(); 27 | Config config = new Config(kaptchaProperties.getProperties()); 28 | 29 | SessionKaptcha sessionKaptcha = new SessionKaptcha(); 30 | 31 | sessionKaptcha.init(config, timeout); 32 | return sessionKaptcha; 33 | } 34 | 35 | @Bean 36 | @ConditionalOnMissingBean 37 | @ConditionalOnProperty(prefix = "spring.kaptcha", name = "store", havingValue = "redis") 38 | public RedisKaptcha redisKaptcha(KaptchaProperties kaptchaProperties) { 39 | 40 | JedisUtil.init(kaptchaProperties.getRedis()); 41 | 42 | long timeout = kaptchaProperties.getTimeout(); 43 | Config config = new Config(kaptchaProperties.getProperties()); 44 | 45 | RedisKaptcha redisKaptcha = new RedisKaptcha(); 46 | 47 | redisKaptcha.init(config, timeout); 48 | return redisKaptcha; 49 | } 50 | 51 | 52 | @Bean 53 | @ConditionalOnMissingBean 54 | public DefaultKaptcha producer(KaptchaProperties kaptchaProperties) { 55 | Config config = new Config(kaptchaProperties.getProperties()); 56 | DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); 57 | defaultKaptcha.setConfig(config); 58 | return defaultKaptcha; 59 | 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter/src/main/java/com/ryanbing/kaptcha/spring/boot/KaptchaProperties.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing.kaptcha.spring.boot; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | import java.util.Properties; 6 | 7 | import static com.ryanbing.kaptcha.spring.boot.KaptchaProperties.KAPTCHA_PREFIX; 8 | 9 | /** 10 | * @author ryanbing 11 | **/ 12 | 13 | @ConfigurationProperties(prefix = KAPTCHA_PREFIX) 14 | public class KaptchaProperties { 15 | 16 | /** 17 | * spring.kaptcha.timeout = 60000 18 | * spring.kaptcha.store = session | redis | mysql 19 | * spring.kaptcha.image.width = 200 20 | * spring.kaptcha.image.height = 50 21 | * spring.kaptcha.textproducer.charstring = abcde2345678gfynmnpwx 22 | * spring.kaptcha.textproducer.charlength = 5 23 | * spring.kaptcha.textproducer.charspace = 2 24 | * spring.kaptcha.textproducer.fontnames = Courier 25 | * spring.kaptcha.textproducer.fontcolor = BLACK 26 | * spring.kaptcha.textproducer.fontsize = 40 27 | */ 28 | 29 | static final String KAPTCHA_PREFIX = "spring.kaptcha"; 30 | 31 | private long timeout = 60000; 32 | 33 | private String store; 34 | 35 | private String redis; 36 | 37 | public String getRedis() { 38 | return redis; 39 | } 40 | 41 | public void setRedis(String redis) { 42 | this.redis = redis; 43 | } 44 | 45 | public long getTimeout() { 46 | return timeout; 47 | } 48 | 49 | public void setTimeout(long timeout) { 50 | this.timeout = timeout; 51 | } 52 | 53 | public String getStore() { 54 | return store; 55 | } 56 | 57 | public void setStore(String store) { 58 | this.store = store; 59 | } 60 | 61 | private Properties properties = new Properties(); 62 | 63 | public Properties getProperties() { 64 | return properties; 65 | } 66 | 67 | public void setProperties(Properties properties) { 68 | this.properties = properties; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter/src/main/java/com/ryanbing/kaptcha/spring/boot/RedisKaptcha.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing.kaptcha.spring.boot; 2 | 3 | import com.google.code.kaptcha.Producer; 4 | import com.google.code.kaptcha.impl.DefaultKaptcha; 5 | import com.google.code.kaptcha.util.Config; 6 | import org.springframework.util.Assert; 7 | import org.springframework.util.StringUtils; 8 | 9 | import javax.imageio.ImageIO; 10 | import javax.servlet.ServletOutputStream; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.awt.image.BufferedImage; 14 | import java.io.IOException; 15 | import java.util.UUID; 16 | 17 | /** 18 | * Redis store 19 | * 20 | * @author ryanbing 21 | **/ 22 | public class RedisKaptcha implements KaptchaAdapter { 23 | 24 | private Producer kaptchaProducer = null; 25 | 26 | private String redisKeyValue = DEFAULT_KEY_VALUE; 27 | 28 | private String redisKeyDateValue = DEFAULT_KEY_DATE_VALUE; 29 | 30 | private long redisKeyTimeout = DEFAULT_TIME_OUT; 31 | 32 | 33 | @Override 34 | public void init() { 35 | if (StringUtils.isEmpty(kaptchaProducer)) { 36 | this.kaptchaProducer = new DefaultKaptcha(); 37 | } 38 | } 39 | 40 | @Override 41 | public void init(Config config, long timeout) { 42 | this.kaptchaProducer = config.getProducerImpl(); 43 | this.redisKeyTimeout = timeout; 44 | } 45 | 46 | @Override 47 | public void init(String keyValue, String keyDateValue, long timeout) { 48 | if (StringUtils.isEmpty(kaptchaProducer)) { 49 | this.kaptchaProducer = new DefaultKaptcha(); 50 | } 51 | this.redisKeyValue = keyValue; 52 | this.redisKeyDateValue = keyDateValue; 53 | this.redisKeyTimeout = timeout; 54 | } 55 | 56 | @Override 57 | public void init(Producer producer, String keyValue, String keyDateValue, long timeout) { 58 | this.kaptchaProducer = producer; 59 | this.redisKeyValue = keyValue; 60 | this.redisKeyDateValue = keyDateValue; 61 | this.redisKeyTimeout = timeout; 62 | } 63 | 64 | @Override 65 | public void setCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException { 66 | setCaptcha(request, response, this.kaptchaProducer.createText()); 67 | } 68 | 69 | @Override 70 | public void setCaptcha(HttpServletRequest request, HttpServletResponse response, String captchaText) throws IOException { 71 | setCaptcha(request, response, null, null, captchaText); 72 | } 73 | 74 | @Override 75 | public void setCaptcha(HttpServletRequest request, HttpServletResponse response, String keyValue, String keyDateValue) throws IOException { 76 | setCaptcha(request, response, keyValue, keyDateValue, this.kaptchaProducer.createText()); 77 | } 78 | 79 | @Override 80 | public void setCaptcha(HttpServletRequest request, HttpServletResponse response, String keyValue, String keyDateValue, String captchaText) throws IOException { 81 | 82 | 83 | Assert.notNull(captchaText, "captcha must not be null"); 84 | String s = request.getRequestURL().toString() + String.valueOf(System.currentTimeMillis()); 85 | UUID uuid = UUID.nameUUIDFromBytes(s.getBytes("UTF-8")); 86 | 87 | this.redisKeyValue = keyValue; 88 | this.redisKeyDateValue = keyDateValue; 89 | 90 | if (keyValue == null) { 91 | this.redisKeyValue = uuid + DEFAULT_KEY_VALUE; 92 | } 93 | if (keyDateValue == null) { 94 | this.redisKeyDateValue = uuid + DEFAULT_KEY_DATE_VALUE; 95 | } 96 | 97 | SessionUtil.setRedisAttribute(response, this.redisKeyValue, captchaText, this.redisKeyTimeout); 98 | 99 | BufferedImage bi = this.kaptchaProducer.createImage(captchaText); 100 | ServletOutputStream out = response.getOutputStream(); 101 | 102 | ImageIO.write(bi, "jpg", out); 103 | 104 | } 105 | 106 | @Override 107 | public boolean validCaptcha(HttpServletRequest request, String captcha) { 108 | 109 | String redisValue = (String) SessionUtil.getRedisAttribute(this.redisKeyValue); 110 | 111 | if (redisValue == null) { 112 | return false; 113 | } 114 | return redisValue.equals(captcha); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter/src/main/java/com/ryanbing/kaptcha/spring/boot/SessionKaptcha.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing.kaptcha.spring.boot; 2 | 3 | import com.google.code.kaptcha.Producer; 4 | import com.google.code.kaptcha.impl.DefaultKaptcha; 5 | import com.google.code.kaptcha.util.Config; 6 | import org.springframework.util.Assert; 7 | import org.springframework.util.StringUtils; 8 | 9 | import javax.imageio.ImageIO; 10 | import javax.servlet.ServletOutputStream; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.awt.image.BufferedImage; 14 | import java.io.IOException; 15 | 16 | /** 17 | * session store captcha 18 | * 19 | * @author ryanbing 20 | **/ 21 | public class SessionKaptcha implements KaptchaAdapter { 22 | 23 | 24 | private Producer kaptchaProducer = null; 25 | 26 | private String sessionKeyValue = DEFAULT_KEY_VALUE; 27 | 28 | private String sessionKeyDateValue = DEFAULT_KEY_DATE_VALUE; 29 | 30 | private long sessionKeyTimeout = DEFAULT_TIME_OUT; 31 | 32 | @Override 33 | public void init() { 34 | if (StringUtils.isEmpty(kaptchaProducer)) { 35 | this.kaptchaProducer = new DefaultKaptcha(); 36 | } 37 | } 38 | 39 | @Override 40 | public void init(Config config, long timeout) { 41 | this.kaptchaProducer = config.getProducerImpl(); 42 | this.sessionKeyTimeout = timeout; 43 | } 44 | 45 | @Override 46 | public void init(String keyValue, String keyDateValue, long timeout) { 47 | if (StringUtils.isEmpty(kaptchaProducer)) { 48 | this.kaptchaProducer = new DefaultKaptcha(); 49 | } 50 | this.sessionKeyValue = keyValue; 51 | this.sessionKeyDateValue = keyDateValue; 52 | this.sessionKeyTimeout = timeout; 53 | } 54 | 55 | @Override 56 | public void init(Producer producer, String keyValue, String keyDateValue, long timeout) { 57 | this.kaptchaProducer = producer; 58 | this.sessionKeyValue = keyValue; 59 | this.sessionKeyDateValue = keyDateValue; 60 | this.sessionKeyTimeout = timeout; 61 | } 62 | 63 | @Override 64 | public void setCaptcha(HttpServletRequest req, HttpServletResponse resp) throws IOException { 65 | setCaptcha(req, resp,this.kaptchaProducer.createText()); 66 | } 67 | 68 | @Override 69 | public void setCaptcha(HttpServletRequest req, HttpServletResponse resp, String captchaText) throws IOException { 70 | Assert.notNull(captchaText, "captchaText must not be null"); 71 | 72 | SessionUtil.setSessionAttribute(req, resp, this.sessionKeyValue, captchaText); 73 | SessionUtil.setSessionAttribute(req, resp, this.sessionKeyDateValue, System.currentTimeMillis()); 74 | 75 | BufferedImage bi = this.kaptchaProducer.createImage(captchaText); 76 | ServletOutputStream out = resp.getOutputStream(); 77 | 78 | ImageIO.write(bi, "jpg", out); 79 | } 80 | 81 | @Override 82 | public void setCaptcha(HttpServletRequest req, HttpServletResponse resp,String keyValue, String keyDateValue) throws IOException{ 83 | setCaptcha(req, resp, keyValue, keyDateValue, this.kaptchaProducer.createText()); 84 | } 85 | 86 | @Override 87 | public void setCaptcha(HttpServletRequest req, HttpServletResponse resp,String keyValue, String keyDateValue, String captchaText) throws IOException{ 88 | Assert.notNull(captchaText, "captcha must not be null"); 89 | 90 | this.sessionKeyValue = keyValue; 91 | this.sessionKeyDateValue = keyDateValue; 92 | SessionUtil.setSessionAttribute(req, resp, this.sessionKeyValue, captchaText); 93 | SessionUtil.setSessionAttribute(req, resp, this.sessionKeyDateValue, System.currentTimeMillis()); 94 | 95 | 96 | 97 | BufferedImage bi = this.kaptchaProducer.createImage(captchaText); 98 | ServletOutputStream out = resp.getOutputStream(); 99 | 100 | ImageIO.write(bi, "jpg", out); 101 | } 102 | 103 | @Override 104 | public boolean validCaptcha(HttpServletRequest request, String captcha) { 105 | Assert.notNull(captcha, "captcha must not be null"); 106 | 107 | String sessionValue = (String) SessionUtil.getSessionAttribute(request, this.sessionKeyValue); 108 | Long sessionDataValue = (Long) SessionUtil.getSessionAttribute(request, this.sessionKeyDateValue); 109 | 110 | if (StringUtils.isEmpty(sessionDataValue)) { 111 | return false; 112 | } 113 | 114 | boolean isTimeout = (System.currentTimeMillis() - sessionDataValue) < this.sessionKeyTimeout; 115 | 116 | return isTimeout && captcha.equalsIgnoreCase(sessionValue); 117 | 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter/src/main/java/com/ryanbing/kaptcha/spring/boot/SessionUtil.java: -------------------------------------------------------------------------------- 1 | package com.ryanbing.kaptcha.spring.boot; 2 | 3 | import org.springframework.lang.Nullable; 4 | import org.springframework.util.Assert; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import javax.servlet.http.HttpSession; 9 | 10 | /** 11 | * @author ryanbing 12 | **/ 13 | class SessionUtil { 14 | 15 | static void setSessionAttribute(HttpServletRequest req, HttpServletResponse resp, String name, @Nullable Object value) { 16 | Assert.notNull(req, "Request must not be null"); 17 | 18 | // Set to expire far in the past. 19 | resp.setDateHeader("Expires", 0); 20 | // Set standard HTTP/1.1 no-cache headers. 21 | resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); 22 | // Set IE extended HTTP/1.1 no-cache headers (use addHeader). 23 | resp.addHeader("Cache-Control", "post-check=0, pre-check=0"); 24 | // Set standard HTTP/1.0 no-cache header. 25 | resp.setHeader("Pragma", "no-cache"); 26 | 27 | // return a jpeg 28 | resp.setContentType("image/jpeg"); 29 | if (value != null) { 30 | req.getSession().setAttribute(name, value); 31 | } else { 32 | HttpSession session = req.getSession(false); 33 | if (session != null) { 34 | session.removeAttribute(name); 35 | } 36 | } 37 | } 38 | 39 | static void setRedisAttribute(HttpServletResponse resp, String name, @Nullable Object value, long timeout) { 40 | 41 | // Set to expire far in the past. 42 | resp.setDateHeader("Expires", 0); 43 | // Set standard HTTP/1.1 no-cache headers. 44 | resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); 45 | // Set IE extended HTTP/1.1 no-cache headers (use addHeader). 46 | resp.addHeader("Cache-Control", "post-check=0, pre-check=0"); 47 | // Set standard HTTP/1.0 no-cache header. 48 | resp.setHeader("Pragma", "no-cache"); 49 | 50 | // return a jpeg 51 | resp.setContentType("image/jpeg"); 52 | if (value != null) { 53 | JedisUtil.setObjectValue(name,value, (int) (timeout/1000)); 54 | } else { 55 | Object sessionId = JedisUtil.getObjectValue(name); 56 | if (sessionId != null) { 57 | JedisUtil.del(name); 58 | } 59 | } 60 | } 61 | 62 | @Nullable 63 | static Object getSessionAttribute(HttpServletRequest request, String name) { 64 | Assert.notNull(request, "Request must not be null"); 65 | HttpSession session = request.getSession(false); 66 | return session != null ? session.getAttribute(name) : null; 67 | } 68 | 69 | @Nullable 70 | static Object getRedisAttribute(String name) { 71 | return JedisUtil.getObjectValue(name); 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /kaptcha-spring-boot-starter/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | com.ryanbing.kaptcha.spring.boot.KaptchaAutoConfiguration -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.ryanbing 8 | captcha-spring-boot-starter 9 | pom 10 | 1.0.1.RELEASE 11 | 12 | 13 | kaptcha-spring-boot-starter 14 | kaptcha-spring-boot-starter-redis-example 15 | kaptcha-spring-boot-starter-session-example 16 | 17 | 18 | 19 | --------------------------------------------------------------------------------