mirror of
https://github.com/librecaptcha/lc-core.git
synced 2025-01-13 06:53:19 -05:00
Merge pull request #90 from rr83019/BT-captcha
Background Thread - Random Captcha Generation
This commit is contained in:
commit
6196a34aae
@ -23,6 +23,7 @@ scalacOptions ++= List(
|
||||
)
|
||||
javacOptions += "-g:none"
|
||||
compileOrder := CompileOrder.JavaThenScala
|
||||
javafmtOnCompile := false
|
||||
assembly / mainClass := Some("lc.LCFramework")
|
||||
Compile / run / mainClass := Some("lc.LCFramework")
|
||||
assembly / assemblyJarName := "LibreCaptcha.jar"
|
||||
|
@ -1,9 +1,16 @@
|
||||
package lc.misc;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Random;
|
||||
|
||||
public class HelperFunctions {
|
||||
|
||||
private static Random random = new Random();
|
||||
|
||||
synchronized public static void setSeed(long seed){
|
||||
random.setSeed(seed);
|
||||
}
|
||||
|
||||
public static void setRenderingHints(Graphics2D g2d) {
|
||||
g2d.setRenderingHint(
|
||||
RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
@ -25,13 +32,18 @@ public class HelperFunctions {
|
||||
public static String randomString(final int n, final String characters) {
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
for (int i = 0; i < n; i++) {
|
||||
int index = (int) (characters.length() * Math.random());
|
||||
int index = randomNumber(characters.length());
|
||||
stringBuilder.append(characters.charAt(index));
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
public static int randomNumber(int min, int max) {
|
||||
return (int) (Math.random() * ((max - min) + 1)) + min;
|
||||
synchronized public static int randomNumber(int min, int max) {
|
||||
return (random.nextInt() * ((max - min) + 1)) + min;
|
||||
}
|
||||
|
||||
synchronized public static int randomNumber(int bound) {
|
||||
return random.nextInt(bound);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,8 +2,9 @@ package lc.background
|
||||
|
||||
import lc.database.Statements
|
||||
import java.util.concurrent.{ScheduledThreadPoolExecutor, TimeUnit}
|
||||
import lc.core.Captcha
|
||||
import lc.core.{Captcha, Config}
|
||||
import lc.core.{Parameters, Size}
|
||||
import lc.misc.HelperFunctions
|
||||
|
||||
class BackgroundTask(throttle: Int, timeLimit: Int) {
|
||||
|
||||
@ -22,13 +23,26 @@ class BackgroundTask(throttle: Int, timeLimit: Int) {
|
||||
if (imageNum.next())
|
||||
throttleIn = (throttleIn - imageNum.getInt("total"))
|
||||
while (0 < throttleIn) {
|
||||
Captcha.generateChallenge(Parameters("medium", "image/png", "text", Option(Size(0, 0))))
|
||||
Captcha.generateChallenge(getRandomParam())
|
||||
throttleIn -= 1
|
||||
}
|
||||
} catch { case exception: Exception => println(exception) }
|
||||
}
|
||||
}
|
||||
|
||||
private def getRandomParam(): Parameters = {
|
||||
val captcha = pickRandom(Config.captchaConfig)
|
||||
val level = pickRandom(captcha.allowedLevels)
|
||||
val media = pickRandom(captcha.allowedMedia)
|
||||
val inputType = pickRandom(captcha.allowedInputType)
|
||||
|
||||
Parameters(level, media, inputType, Some(Size(0, 0)))
|
||||
}
|
||||
|
||||
private def pickRandom[T](list: List[T]): T = {
|
||||
list(HelperFunctions.randomNumber(list.size))
|
||||
}
|
||||
|
||||
def beginThread(delay: Int): Unit = {
|
||||
val ex = new ScheduledThreadPoolExecutor(1)
|
||||
ex.scheduleWithFixedDelay(task, 1, delay, TimeUnit.SECONDS)
|
||||
|
@ -4,6 +4,7 @@ import lc.captchas._
|
||||
import lc.captchas.interfaces.ChallengeProvider
|
||||
import lc.captchas.interfaces.Challenge
|
||||
import scala.collection.mutable.Map
|
||||
import lc.misc.HelperFunctions
|
||||
|
||||
object CaptchaProviders {
|
||||
private val providers = Map(
|
||||
@ -23,15 +24,8 @@ object CaptchaProviders {
|
||||
}
|
||||
}
|
||||
|
||||
private val seed = Config.seed
|
||||
private val random = new scala.util.Random(seed)
|
||||
private val config = Config.captchaConfig
|
||||
|
||||
private def getNextRandomInt(max: Int): Int =
|
||||
random.synchronized {
|
||||
random.nextInt(max)
|
||||
}
|
||||
|
||||
def getProviderById(id: String): ChallengeProvider = {
|
||||
return providers(id)
|
||||
}
|
||||
@ -58,7 +52,7 @@ object CaptchaProviders {
|
||||
def getProvider(param: Parameters): Option[ChallengeProvider] = {
|
||||
val providerConfig = filterProviderByParam(param).toList
|
||||
if (providerConfig.length > 0) {
|
||||
val randomIndex = getNextRandomInt(providerConfig.length)
|
||||
val randomIndex = HelperFunctions.randomNumber(providerConfig.length)
|
||||
val providerIndex = providerConfig(randomIndex)._1
|
||||
val selectedProvider = providers(providerIndex)
|
||||
selectedProvider.configure(providerConfig(randomIndex)._2)
|
||||
|
@ -6,6 +6,7 @@ import org.json4s.jackson.JsonMethods.{parse, render, pretty}
|
||||
import org.json4s.JsonDSL._
|
||||
import java.io.{FileNotFoundException, File, PrintWriter}
|
||||
import java.{util => ju}
|
||||
import lc.misc.HelperFunctions
|
||||
|
||||
object Config {
|
||||
|
||||
@ -49,6 +50,8 @@ object Config {
|
||||
val allowedMedia: Set[String] = captchaConfig.flatMap(_.allowedMedia).toSet
|
||||
val allowedInputType: Set[String] = captchaConfig.flatMap(_.allowedInputType).toSet
|
||||
|
||||
HelperFunctions.setSeed(seed)
|
||||
|
||||
private def getDefaultConfig(): String = {
|
||||
val defaultConfigMap =
|
||||
(AttributesEnum.RANDOM_SEED.toString -> new ju.Random().nextInt()) ~
|
||||
|
@ -116,7 +116,7 @@ object Statements {
|
||||
org.h2.jdbc.JdbcSQLNonTransientException: General error: "java.lang.NullPointerException"; SQL statement:
|
||||
SELECT image FROM challenge c, mapId m WHERE c.token=m.token AND m.uuid = ? [50000-200]
|
||||
```
|
||||
*/
|
||||
*/
|
||||
private val dbConn: DBConn = new DBConn()
|
||||
private val maxAttempts = 10
|
||||
val tlStmts: ThreadLocal[Statements] = ThreadLocal.withInitial(() => new Statements(dbConn, maxAttempts))
|
||||
|
@ -11,37 +11,50 @@ import scala.io.Source
|
||||
import org.limium.picoserve.Server.StringResponse
|
||||
|
||||
class Server(port: Int) {
|
||||
val server: picoserve.Server = picoserve.Server.builder()
|
||||
val server: picoserve.Server = picoserve.Server
|
||||
.builder()
|
||||
.port(port)
|
||||
.backlog(32)
|
||||
.POST("/v1/captcha", (request) => {
|
||||
val json = parse(request.getBodyString())
|
||||
val param = json.extract[Parameters]
|
||||
val id = Captcha.getChallenge(param)
|
||||
getResponse(id)
|
||||
})
|
||||
.GET("/v1/media", (request) => {
|
||||
val params = request.getQueryParams()
|
||||
val result = if (params.containsKey("id")) {
|
||||
val paramId = params.get("id").get(0)
|
||||
val id = Id(paramId)
|
||||
Captcha.getCaptcha(id)
|
||||
} else {
|
||||
Left(Error(ErrorMessageEnum.INVALID_PARAM.toString + "=> id"))
|
||||
.POST(
|
||||
"/v1/captcha",
|
||||
(request) => {
|
||||
val json = parse(request.getBodyString())
|
||||
val param = json.extract[Parameters]
|
||||
val id = Captcha.getChallenge(param)
|
||||
getResponse(id)
|
||||
}
|
||||
getResponse(result)
|
||||
})
|
||||
.POST("/v1/answer", (request) => {
|
||||
val json = parse(request.getBodyString())
|
||||
val answer = json.extract[Answer]
|
||||
val result = Captcha.checkAnswer(answer)
|
||||
getResponse(result)
|
||||
})
|
||||
.GET("/demo/index.html", (_) => {
|
||||
val resStream = getClass().getResourceAsStream("/index.html")
|
||||
val str = Source.fromInputStream(resStream).mkString
|
||||
new StringResponse(200, str)
|
||||
})
|
||||
)
|
||||
.GET(
|
||||
"/v1/media",
|
||||
(request) => {
|
||||
val params = request.getQueryParams()
|
||||
val result = if (params.containsKey("id")) {
|
||||
val paramId = params.get("id").get(0)
|
||||
val id = Id(paramId)
|
||||
Captcha.getCaptcha(id)
|
||||
} else {
|
||||
Left(Error(ErrorMessageEnum.INVALID_PARAM.toString + "=> id"))
|
||||
}
|
||||
getResponse(result)
|
||||
}
|
||||
)
|
||||
.POST(
|
||||
"/v1/answer",
|
||||
(request) => {
|
||||
val json = parse(request.getBodyString())
|
||||
val answer = json.extract[Answer]
|
||||
val result = Captcha.checkAnswer(answer)
|
||||
getResponse(result)
|
||||
}
|
||||
)
|
||||
.GET(
|
||||
"/demo/index.html",
|
||||
(_) => {
|
||||
val resStream = getClass().getResourceAsStream("/index.html")
|
||||
val str = Source.fromInputStream(resStream).mkString
|
||||
new StringResponse(200, str)
|
||||
}
|
||||
)
|
||||
.build()
|
||||
|
||||
private def getResponse(response: Either[Error, ByteConvert]): ByteResponse = {
|
||||
|
Loading…
Reference in New Issue
Block a user