mirror of
https://github.com/exzork/GCAuth.git
synced 2025-01-30 14:08:36 +00:00
add ratelimit
This commit is contained in:
parent
738a642dba
commit
de6438e063
14
README.md
14
README.md
@ -46,4 +46,16 @@ Grasscutter Authentication System
|
||||
- `jwt` : JWT token if success with body :
|
||||
- `token` : Token used for authentication, paste it in username field of client.
|
||||
- `username` : Username of the user.
|
||||
- `uid` : UID of the user.
|
||||
- `uid` : UID of the user.
|
||||
|
||||
## Config :
|
||||
- hash : Hash algorithm used for password hashing. (Only Bcrypt and Scrypt is supported)
|
||||
- jwtSecret : Secret used for JWT token.
|
||||
- jwtExpiration : Expiration time of JWT token.
|
||||
- otpExpiration : Expiration time of OTP.
|
||||
- defaultPermission : Default permission of user.
|
||||
- accessKey : Access key used for access control. (Optional)
|
||||
- rateLimit :
|
||||
- maxRequests : Maximum requests per timeUnit.
|
||||
- timeUnit : Time unit of rateLimit. (seconds, minutes, hours, days)
|
||||
- endPoints[] : Endpoint to rate limit. (login, register, change_password)
|
@ -10,7 +10,7 @@ sourceCompatibility = 17
|
||||
targetCompatibility = 17
|
||||
|
||||
group 'me.exzork.gcauth'
|
||||
version '2.3.1'
|
||||
version '2.4.0'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
@ -3,10 +3,16 @@ package me.exzork.gcauth;
|
||||
import me.exzork.gcauth.utils.Authentication;
|
||||
|
||||
public final class Config {
|
||||
public String Hash = "BCRYPT";
|
||||
public String hash = "BCRYPT";
|
||||
public String jwtSecret = Authentication.generateRandomString(32);
|
||||
public long jwtExpiration = 86400;
|
||||
public long otpExpiration = 300;
|
||||
public String[] defaultPermissions = new String[]{""};
|
||||
public String accessKey = "";
|
||||
public RateLimit rateLimit = new RateLimit();
|
||||
public static class RateLimit {
|
||||
public int maxRequests = 10;
|
||||
public String timeUnit = "MINUTES";
|
||||
public String[] endPoints = new String[]{"login","register","change_password"};
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
package me.exzork.gcauth.handler;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.mchange.v1.util.ArrayUtils;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.auth.AuthenticationSystem;
|
||||
import emu.grasscutter.auth.ExternalAuthenticator;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.Account;
|
||||
import express.http.Response;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.util.RateLimit;
|
||||
import me.exzork.gcauth.GCAuth;
|
||||
import me.exzork.gcauth.json.AuthResponseJson;
|
||||
import me.exzork.gcauth.json.ChangePasswordAccount;
|
||||
@ -14,13 +17,20 @@ import me.exzork.gcauth.json.LoginGenerateToken;
|
||||
import me.exzork.gcauth.json.RegisterAccount;
|
||||
import me.exzork.gcauth.utils.Authentication;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class GCAuthExternalAuthenticator implements ExternalAuthenticator {
|
||||
private String[] endPoints = GCAuth.getInstance().getConfig().rateLimit.endPoints;
|
||||
private int maxRequests = GCAuth.getInstance().getConfig().rateLimit.maxRequests;
|
||||
private String timeUnit = GCAuth.getInstance().getConfig().rateLimit.timeUnit;
|
||||
@Override
|
||||
public void handleLogin(AuthenticationSystem.AuthenticationRequest authenticationRequest) {
|
||||
AuthResponseJson authResponse = new AuthResponseJson();
|
||||
Response response = authenticationRequest.getResponse();
|
||||
assert response != null; // This should never be null.
|
||||
|
||||
if (Arrays.asList(endPoints).contains("login"))
|
||||
new RateLimit(response.ctx()).requestPerTimeUnit(maxRequests, Authentication.getTimeUnit(timeUnit));
|
||||
try {
|
||||
String requestBody = response.ctx().body();
|
||||
if (requestBody.isEmpty()) {
|
||||
@ -67,7 +77,8 @@ public class GCAuthExternalAuthenticator implements ExternalAuthenticator {
|
||||
AuthResponseJson authResponse = new AuthResponseJson();
|
||||
Response response = authenticationRequest.getResponse();
|
||||
assert response != null; // This should never be null.
|
||||
|
||||
if (Arrays.asList(endPoints).contains("register"))
|
||||
new RateLimit(response.ctx()).requestPerTimeUnit(maxRequests, Authentication.getTimeUnit(timeUnit));
|
||||
Account account = null;
|
||||
try {
|
||||
String requestBody = response.ctx().body();
|
||||
@ -145,7 +156,8 @@ public class GCAuthExternalAuthenticator implements ExternalAuthenticator {
|
||||
AuthResponseJson authResponse = new AuthResponseJson();
|
||||
Response response = authenticationRequest.getResponse();
|
||||
assert response != null; // This should never be null.
|
||||
|
||||
if (Arrays.asList(endPoints).contains("change_password"))
|
||||
new RateLimit(response.ctx()).requestPerTimeUnit(maxRequests, Authentication.getTimeUnit(timeUnit));
|
||||
try {
|
||||
String requestBody = response.ctx().body();
|
||||
if (requestBody.isEmpty()) {
|
||||
@ -172,12 +184,11 @@ public class GCAuthExternalAuthenticator implements ExternalAuthenticator {
|
||||
account.save();
|
||||
authResponse.success = true;
|
||||
authResponse.message = "";
|
||||
authResponse.jwt = "";
|
||||
} else {
|
||||
authResponse.success = false;
|
||||
authResponse.message = "PASSWORD_INVALID"; // ENG = "Password must be at least 8 characters long"
|
||||
authResponse.jwt = "";
|
||||
}
|
||||
authResponse.jwt = "";
|
||||
}
|
||||
} else {
|
||||
authResponse.success = false;
|
||||
|
@ -13,6 +13,7 @@ import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class Authentication {
|
||||
public static final HashMap<String, String> otps = new HashMap<>();
|
||||
@ -77,7 +78,7 @@ public final class Authentication {
|
||||
}
|
||||
|
||||
public static String generateHash(String password) {
|
||||
return switch (GCAuth.getInstance().getConfig().Hash.toLowerCase()) {
|
||||
return switch (GCAuth.getInstance().getConfig().hash.toLowerCase()) {
|
||||
case "bcrypt" -> new BCryptPasswordEncoder().encode(password);
|
||||
case "scrypt" -> new SCryptPasswordEncoder().encode(password);
|
||||
default -> password;
|
||||
@ -85,7 +86,7 @@ public final class Authentication {
|
||||
}
|
||||
|
||||
private static boolean verifyPassword(String password, String hash) {
|
||||
return switch (GCAuth.getInstance().getConfig().Hash.toLowerCase()) {
|
||||
return switch (GCAuth.getInstance().getConfig().hash.toLowerCase()) {
|
||||
case "bcrypt" -> new BCryptPasswordEncoder().matches(password, hash);
|
||||
case "scrypt" -> new SCryptPasswordEncoder().matches(password, hash);
|
||||
default -> password.equals(hash);
|
||||
@ -114,4 +115,14 @@ public final class Authentication {
|
||||
}
|
||||
},GCAuth.getInstance().getConfig().otpExpiration * 1000);
|
||||
}
|
||||
|
||||
public static TimeUnit getTimeUnit(String timeUnit) {
|
||||
return switch (timeUnit.toLowerCase()) {
|
||||
case "seconds" -> TimeUnit.SECONDS;
|
||||
case "minutes" -> TimeUnit.MINUTES;
|
||||
case "hours" -> TimeUnit.HOURS;
|
||||
case "days" -> TimeUnit.DAYS;
|
||||
default -> TimeUnit.MINUTES;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user