From 5c0ee81bfbd27c8a0eac7ddaee2367ff88f2777d Mon Sep 17 00:00:00 2001 From: gsd Date: Wed, 1 Mar 2023 16:18:51 +0300 Subject: [PATCH] rewrite web access --- .../app/annotations/enums/AuthMethod.java | 7 ++++ .../exceptions/FailedAuthCheck.java | 4 ++ .../app/annotations/impl/WebAccessAspect.java | 40 +++++++++++++++---- .../interfaces/CheckWebAccess.java | 3 ++ .../discord/DiscordController.java | 32 +++++++++++++++ .../handler/GlobalExceptionAdvice.java | 14 +++++-- .../app/services/db/DiscordAuthService.java | 22 ++++++++++ 7 files changed, 111 insertions(+), 11 deletions(-) create mode 100644 src/main/java/app/annotations/enums/AuthMethod.java create mode 100644 src/main/java/app/annotations/exceptions/FailedAuthCheck.java create mode 100644 src/main/java/app/controllers/discord/DiscordController.java create mode 100644 src/main/java/app/services/db/DiscordAuthService.java diff --git a/src/main/java/app/annotations/enums/AuthMethod.java b/src/main/java/app/annotations/enums/AuthMethod.java new file mode 100644 index 0000000..e579d90 --- /dev/null +++ b/src/main/java/app/annotations/enums/AuthMethod.java @@ -0,0 +1,7 @@ +package app.annotations.enums; + +public enum AuthMethod { + STEAM64, + SECRET_KEY, + COMBINED +} diff --git a/src/main/java/app/annotations/exceptions/FailedAuthCheck.java b/src/main/java/app/annotations/exceptions/FailedAuthCheck.java new file mode 100644 index 0000000..e42e74e --- /dev/null +++ b/src/main/java/app/annotations/exceptions/FailedAuthCheck.java @@ -0,0 +1,4 @@ +package app.annotations.exceptions; + +public class FailedAuthCheck extends RuntimeException{ +} diff --git a/src/main/java/app/annotations/impl/WebAccessAspect.java b/src/main/java/app/annotations/impl/WebAccessAspect.java index e3753ac..0608d2f 100644 --- a/src/main/java/app/annotations/impl/WebAccessAspect.java +++ b/src/main/java/app/annotations/impl/WebAccessAspect.java @@ -1,12 +1,16 @@ package app.annotations.impl; +import app.annotations.enums.AuthMethod; import app.annotations.exceptions.InvalidCookie; import app.annotations.exceptions.InvalidSecretKey; import app.annotations.exceptions.NeedCookie; +import app.annotations.interfaces.CheckWebAccess; import app.utils.SaltedCookie; import jakarta.servlet.http.HttpServletRequest; +import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; @@ -21,7 +25,8 @@ public class WebAccessAspect { } @Before("@annotation(app.annotations.interfaces.CheckWebAccess) && args(request,..)") - public void before(HttpServletRequest request){ + public void before(JoinPoint joinPoint, HttpServletRequest request){ + AuthMethod auth_method = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(CheckWebAccess.class).auth_method(); System.out.println("check web access"); if(!(request instanceof HttpServletRequest)) { throw new RuntimeException("cannot read cookie from invalid request"); @@ -53,20 +58,39 @@ public class WebAccessAspect { } } - if (!secret_key.isEmpty() && !steam64.isEmpty()) { - if (saltedCookie.ValidateSecretKey(secret_key)) { - System.out.println("used secret key"); - return; - } else { - throw new InvalidSecretKey(); + switch (auth_method){ + case COMBINED -> { + if (!secret_key.isEmpty() && !steam64.isEmpty()) { + if (saltedCookie.ValidateSecretKey(secret_key)) { + System.out.println("used secret key with steamid"); + return; + } else { + throw new InvalidSecretKey(); + } + } + CheckSteamID(steam64, steam64_secured); + } + case SECRET_KEY -> { + if (secret_key.isEmpty()) throw new InvalidSecretKey(); + if (saltedCookie.ValidateSecretKey(secret_key)) { + System.out.println("used secret key without steamid"); + return; + } else { + throw new InvalidSecretKey(); + } + } + case STEAM64 -> { + CheckSteamID(steam64, steam64_secured); } } + } + public void CheckSteamID(String steam64, String steam64_secured) { if (steam64.isEmpty() || steam64_secured.isEmpty()) { throw new NeedCookie(); } - if(!saltedCookie.Validate(steam64, steam64_secured)) { + if (!saltedCookie.Validate(steam64, steam64_secured)) { throw new InvalidCookie(); } } diff --git a/src/main/java/app/annotations/interfaces/CheckWebAccess.java b/src/main/java/app/annotations/interfaces/CheckWebAccess.java index 621a2f1..f6729eb 100644 --- a/src/main/java/app/annotations/interfaces/CheckWebAccess.java +++ b/src/main/java/app/annotations/interfaces/CheckWebAccess.java @@ -1,5 +1,7 @@ package app.annotations.interfaces; +import app.annotations.enums.AuthMethod; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -8,4 +10,5 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface CheckWebAccess { + public AuthMethod auth_method() default AuthMethod.COMBINED; } diff --git a/src/main/java/app/controllers/discord/DiscordController.java b/src/main/java/app/controllers/discord/DiscordController.java new file mode 100644 index 0000000..eef7449 --- /dev/null +++ b/src/main/java/app/controllers/discord/DiscordController.java @@ -0,0 +1,32 @@ +package app.controllers.discord; + +import app.annotations.enums.AuthMethod; +import app.annotations.interfaces.CheckWebAccess; +import app.entities.other.SteamID; +import app.services.db.DiscordAuthService; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("api/discord") +public class DiscordController { + DiscordAuthService discordAuthService; + + @Autowired + public DiscordController(DiscordAuthService discordAuthService) { + this.discordAuthService = discordAuthService; + } + + @GetMapping + @CheckWebAccess(auth_method = AuthMethod.SECRET_KEY) + public ResponseEntity getSteamID(HttpServletRequest request, + @RequestParam String discord_id) { + return new ResponseEntity(discordAuthService.getSteamIDofDiscordID(discord_id), HttpStatus.OK); + } +} diff --git a/src/main/java/app/exceptions/handler/GlobalExceptionAdvice.java b/src/main/java/app/exceptions/handler/GlobalExceptionAdvice.java index a5d7112..5b7c7e8 100644 --- a/src/main/java/app/exceptions/handler/GlobalExceptionAdvice.java +++ b/src/main/java/app/exceptions/handler/GlobalExceptionAdvice.java @@ -1,8 +1,6 @@ package app.exceptions.handler; -import app.annotations.exceptions.InvalidCookie; -import app.annotations.exceptions.LowPermition; -import app.annotations.exceptions.NeedCookie; +import app.annotations.exceptions.*; import app.exceptions.steam.InvalidSteamID; import org.springframework.http.HttpEntity; import org.springframework.http.HttpStatus; @@ -31,4 +29,14 @@ public class GlobalExceptionAdvice { public ResponseEntity handInvalidSteamID() { return new ResponseEntity(HttpStatus.NOT_FOUND); } + + @ExceptionHandler(InvalidSecretKey.class) + public ResponseEntity handInvalidSecretKey() { + return new ResponseEntity(HttpStatus.UNAUTHORIZED); + } + + @ExceptionHandler(FailedAuthCheck.class) + public ResponseEntity handFailedAuthCheck() { + return new ResponseEntity(HttpStatus.UNAUTHORIZED); + } } diff --git a/src/main/java/app/services/db/DiscordAuthService.java b/src/main/java/app/services/db/DiscordAuthService.java new file mode 100644 index 0000000..9e34011 --- /dev/null +++ b/src/main/java/app/services/db/DiscordAuthService.java @@ -0,0 +1,22 @@ +package app.services.db; + +import app.entities.other.SteamID; +import app.utils.SteamIDConverter; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import org.springframework.stereotype.Service; + +@Service +public class DiscordAuthService { + @PersistenceContext + EntityManager entityManager; + + public SteamID getSteamIDofDiscordID(String discord_id) { + return (SteamID) entityManager.createNativeQuery("SELECT steam_id FROM steam2discord WHERE discord_id = ?1 AND active = 1 LIMIT 1") + .setParameter(1, discord_id) + .getResultStream() + .map(obj -> SteamIDConverter.getSteamID((String) obj)) + .findFirst() + .orElse(null); + } +}