GithubHelp home page GithubHelp logo

anji-plus / captcha Goto Github PK

View Code? Open in Web Editor NEW
1.3K 20.0 306.0 82.15 MB

行为验证码(滑动拼图、点选文字),前后端(java)交互,包含h5/Android/IOS/flutter/uni-app的源码和实现

Home Page: https://captcha.anji-plus.com/

License: Apache License 2.0

Java 77.49% Kotlin 2.71% Swift 2.51% Objective-C 2.56% Dart 5.28% Ruby 0.03% SCSS 0.11% Less 0.08% PHP 6.60% TypeScript 0.62% Go 1.99%
java vue captcha flutter uni-app

captcha's Introduction

LicenseTotal Lines

AjPlus Captcha

Stargazers over time Stargazers over time

EN docCN doc

1. Online Demo

  1.1 Have a try

  1.2 Document

  1.3 Wechat/H5 demo(based on uni-app)

   see also gitee

Wechat  h5     Wechat Demo            

2. Design Details

  2.1 UI Component

   support Android、iOS、Futter、Uni-App、ReactNative、Vue、Angular、Html、Php。

blockPuzzle clickWord
blockPuzzle clickWord
1-1 1-2

  2.2 Concept Related

concept desc
Captcha Type blockPuzzle, clickWord
Check user action: drag block or click workds,then check if it was human did
Verify bind user action with backend service. call captchaService.verification in backend service to prevent invalid access ,for example,directly call it

  2.3 Main Features

CAPTCHA stands for Completely Automated Public Turing test to tell Computers and Humans Apart. CAPTCHA determines whether the user is real or a spam robot. CAPTCHAs stretch or manipulate letters and numbers, and rely on human ability to determine which symbols they are.

Ajplus Captcha , an open source toolset for users,its main Features are as follows:

  • Easy to integrate ui Component in your apps,support varies frontend UI,
  • Support Integrate with Android、iOS、Futter、Uni-App、ReactNative、Vue、Angular、Html、Php
  • No dependencies lib in core source,Easy to include in your backend service
  • Core api is simple and Open to Extend,all instance initialized by JAVA SPI,Easy to add your custom Implement to form a new Captcha type。
  • Support security feature

3. How to Integrate

Sequence Diagram

4. SourceCode Structure

输入图片说明

5. Dev & Run

  • start backend service import source code into Eclipse or Intellij, start StartApplication class in package service/springboot。online images
  • start frontend ui open source files in view/vue with your IDE like Visual Code,
    npm install
    npm run dev

    DONE  Compiled successfully in 29587ms                       12:06:38
    I  Your application is running here: http://localhost:8081

6. Work Plan

issues

7. Connect Us

[Wechat group] (https://captcha.anji-plus.com/static/weixin.png)

Wechat qq

Thank you, JetBrains, for your support


### Have a try & enjoy it !!! ☺

captcha's People

Contributors

bigbigsky avatar cheartbeat avatar coding-now avatar keanyuan avatar lltx avatar miwei230 avatar pointevent avatar q845655058 avatar qlsjj avatar raodeming avatar seepine avatar testsling avatar wemooly avatar wujiangwu avatar zhouhuan751312 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

captcha's Issues

Maven坐标命名是不是建议调整一下

SpringBoot 提供的 starter 以 spring-boot-starter-xxx 的形式命名。

为了与 SpringBoot 生态提供的 starter 进行区分,官方建议第三方开发者或技术(例如 Druid、Mybatis 等等)厂商自定义的 starter 使用 xxx-spring-boot-starter 的形式命名,例如 mybatis-spring-boot-starter、druid-spring-boot-starter 等等。

底图读取问题

是否支持读取外部库里的图片,而非仅仅只是项目本地的固定路径中的图片

Java后端代码中Redis缓存中验证错误次数似乎存储了字符串类型导致incr失败

使用版本:

com.anji-plus
spring-boot-starter-captcha
1.3.0

在AbstractCaptchaService类中的如下方法:
protected void afterValidateFail(CaptchaVO data) {
if (limitHandler != null) {
// 验证失败 分钟内计数
String fails = String.format(FrequencyLimitHandler.LIMIT_KEY, "FAIL", data.getClientUid());
CaptchaCacheService cs = getCacheService(cacheType);
if (!cs.exists(fails)) {
cs.set(fails, "1", 60);
}
cs.increment(fails, 1);
}
}
incr会爆出ERR wrong number of arguments for 'incr' command错误

希望可以增加自己自定义皮肤功能

1、简单看了一下源码,很多样式都是写在js里的,想自己写样式比较困难
2、希望尽量将样式相关的内容写在css里,这样就算是复写css修改样式也容易很多
3、说实话默认样式真的是不够精致,可以完善一下

uni-app上h5模式不会调用success

code:
<Verify
@success="verifyChecked"
:mode="'pop'"
:captchaType="'blockPuzzle'"
:imgSize="{ width: '260px', height: '155px' }"
:phone="phone"
ref="verify"

代码如上,uni-app中以app模式运行验证码校验通过会执行success回调,但以uni-app的h5模式运行当验证码校验通过并不会执行success回调,验证码窗口为刷新验证码不会关闭验证码窗口

class path resource [images/jigsaw/slidingBlock/] cannot be resolved to URL because it does not exist

supported-captchaCache-service:[local]
java.io.FileNotFoundException: class path resource [images/jigsaw/slidingBlock/] cannot be resolved to URL because it does not exist
	at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:226)
	at org.springframework.core.io.support.PathMatchingResourcePatternResolver.findPathMatchingResources(PathMatchingResourcePatternResolver.java:561)
	at org.springframework.core.io.support.PathMatchingResourcePatternResolver.getResources(PathMatchingResourcePatternResolver.java:344)
	at com.anji.captcha.config.AjCaptchaServiceAutoConfiguration.getResourcesImagesFile(AjCaptchaServiceAutoConfiguration.java:81)
	at com.anji.captcha.config.AjCaptchaServiceAutoConfiguration.initializeBaseMap(AjCaptchaServiceAutoConfiguration.java:73)
	at com.anji.captcha.config.AjCaptchaServiceAutoConfiguration.captchaService(AjCaptchaServiceAutoConfiguration.java:65)
	at com.anji.captcha.config.AjCaptchaServiceAutoConfiguration$$SpringCGLIB$$0.CGLIB$captchaService$0(<generated>)
	at com.anji.captcha.config.AjCaptchaServiceAutoConfiguration$$SpringCGLIB$$2.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258)
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
	at com.anji.captcha.config.AjCaptchaServiceAutoConfiguration$$SpringCGLIB$$0.captchaService(<generated>)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:139)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:647)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1332)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1162)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1417)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:710)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:693)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:133)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:482)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1416)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:597)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:941)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:733)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:435)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1305)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1294)
	at com.MemberApplication.main(MemberApplication.java:16)

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2023-05-30T12:03:34.121+08:00 ERROR 63841 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'captchaController': Lookup method resolution failed
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.checkLookupMethods(AutowiredAnnotationBeanPostProcessor.java:471) ~[spring-beans-6.0.9.jar:6.0.9]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:341) ~[spring-beans-6.0.9.jar:6.0.9]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1291) ~[spring-beans-6.0.9.jar:6.0.9]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1186) ~[spring-beans-6.0.9.jar:6.0.9]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560) ~[spring-beans-6.0.9.jar:6.0.9]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.9.jar:6.0.9]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.9.jar:6.0.9]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.9.jar:6.0.9]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.9.jar:6.0.9]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.9.jar:6.0.9]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973) ~[spring-beans-6.0.9.jar:6.0.9]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:941) ~[spring-context-6.0.9.jar:6.0.9]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) ~[spring-context-6.0.9.jar:6.0.9]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.1.0.jar:3.1.0]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:733) ~[spring-boot-3.1.0.jar:3.1.0]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:435) ~[spring-boot-3.1.0.jar:3.1.0]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:311) ~[spring-boot-3.1.0.jar:3.1.0]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1305) ~[spring-boot-3.1.0.jar:3.1.0]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1294) ~[spring-boot-3.1.0.jar:3.1.0]
	at com.MemberApplication.main(MemberApplication.java:16) ~[classes/:na]
Caused by: java.lang.IllegalStateException: Failed to introspect Class [com.anji.captcha.controller.CaptchaController] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@251a69d7]
	at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:483) ~[spring-core-6.0.9.jar:6.0.9]
	at org.springframework.util.ReflectionUtils.doWithLocalMethods(ReflectionUtils.java:320) ~[spring-core-6.0.9.jar:6.0.9]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.checkLookupMethods(AutowiredAnnotationBeanPostProcessor.java:449) ~[spring-beans-6.0.9.jar:6.0.9]
	... 19 common frames omitted
Caused by: java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest
	at java.base/java.lang.Class.getDeclaredMethods0(Native Method) ~[na:na]
	at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3402) ~[na:na]
	at java.base/java.lang.Class.getDeclaredMethods(Class.java:2504) ~[na:na]
	at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:465) ~[spring-core-6.0.9.jar:6.0.9]
	... 21 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.servlet.http.HttpServletRequest
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na]
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[na:na]
	... 25 common frames omitted


Process finished with exit code 1

如何优雅的重写 ClickWordCaptchaServiceImpl#get()

目前重写后,给新类加@component,会导致 com.anji.captcha.config.AjCaptchaServiceAutoConfiguration#captchaService 不执行,因为它有 @ConditionalOnMissingBean。

如何优雅的干这件事呢,因为我想自定义验证码,比如透明度啥的

CacheUtil 内清理缓存的线程,影响了优雅停机

调用spring boot提供的shutdown接口后,观察线程池还有 thd-captcha-cache-clean 非守护线程未关闭,尝试寻找 CacheUtil 是否有提供该线程池实例的 shutdown 方法发现并没有提供,希望能统一提供关闭相关资源的方法,不要影响优雅停机

验证码坐标建议

建议

captcha_get:接口获取数据过程中,backend会把point存储在redis里面,其实可以使用jwe技术把point存在token返回。
在不同的机器上可以使用相同的key进行payload的解码和exp的校验

你好,是否可以支持png以外的图片格式?

本人学艺不精,万一说错还请见谅
java部分代码中发现,getResourcesImagesFile,等方法,都写死了png格式。
我能理解那一小块拼图必须是png,但好像没必要2类原图也都是png
考虑到现在云主机的带宽贵到起飞,png压缩后也要30kb+ , jpg可以压缩到8kb+ 用户同时并发访问多的时候,不容易出现默认底图,用户不容易流失在这一步。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.