[+] Securing allnet requests

pull/14/head
Azalea 2024-02-25 23:09:56 -05:00
parent cb96b5fa8f
commit b1b2ff6b8c
2 changed files with 105 additions and 9 deletions

View File

@ -154,15 +154,15 @@ class AllNet(
val addr = props.host.ifBlank { localAddr }
val port = props.port?.toString() ?: localPort
return when (gameId) {
"SDBT" -> "http://$addr:$port/g/chu2/$ver/$serial/"
"SDHD" -> "http://$addr:$port/g/chu3/$ver/"
"SBZV" -> "http://$addr:$port/g/diva/"
"SDDT" -> "http://$addr:$port/g/ongeki/"
"SDEY" -> "http://$addr:$port/g/mai/"
"SDEZ" -> "http://$addr:$port/g/mai2/"
"SDED" -> "http://$addr:$port/g/card/"
else -> "http://$addr:$port/"
return "http://$addr:$port" + when (gameId) {
"SDBT" -> "/g/chu2/$ver/$serial/"
"SDHD" -> "/g/chu3/$ver/"
"SBZV" -> "/g/diva/"
"SDDT" -> "/g/ongeki/"
"SDEY" -> "/g/mai/"
"SDEZ" -> "/g/mai2/"
"SDED" -> "/g/card/"
else -> ""
}
}

View File

@ -0,0 +1,96 @@
package icu.samnyan.aqua.sega.allnet
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletRequestWrapper
import jakarta.servlet.http.HttpServletResponse
import org.slf4j.LoggerFactory
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.context.annotation.Configuration
import org.springframework.stereotype.Component
import org.springframework.web.servlet.HandlerInterceptor
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
/**
* Handle token check for secure requests.
*
* When checkKeychip is enabled, the game URLs will be set to /gs/SS{token}/{game}/...
* This interceptor will check if the token exists in the database.
*/
@Component
class TokenChecker(
val keyChipRepo: KeyChipRepo
) : HandlerInterceptor {
val log = LoggerFactory.getLogger(TokenChecker::class.java)
/**
* Handle request before it's processed.
*/
override fun preHandle(req: HttpServletRequest, resp: HttpServletResponse, handler: Any): Boolean {
val token = extractTokenFromPath(req.requestURI)
log.debug("PreHandle: ${req.requestURI} from ip ${req.remoteAddr}, token: $token")
// Check whether the token exists in the database
// The token can either be a keychip id (old method) or a session id (new method)
if (token != null && keyChipRepo.existsByKeychipId(token))
{
// Forward the request
val w = RewriteWrapper(req)
req.getRequestDispatcher(w.requestURI).forward(w, resp)
// Prevent the request from being processed twice
return false
}
// Token doesn't exist, reject the request
resp.status = HttpServletResponse.SC_FORBIDDEN
log.warn("Request rejected: ${req.requestURI} from ip ${req.remoteAddr}")
return false
}
/**
* Extract the token from the request path.
* Example: "/gs/SS12033897/mai2/SomeEndpoint" -> "12033897"
*/
fun extractTokenFromPath(path: String) = path.split("/").find { it.startsWith("SS") }?.substring(2)
}
val tokenRegex = Regex("/gs/SS.*?/")
/**
* Request wrapper for rewriting the URI after token check.
*/
class RewriteWrapper(req: HttpServletRequest) : HttpServletRequestWrapper(req) {
val newUri = req.requestURI.replace(tokenRegex, "/g/")
val newUrl = req.requestURL.toString().replace(tokenRegex, "/g/")
val newSp = req.servletPath.replace(tokenRegex, "/g/")
init {
println("RewriteWrapper: $newUri, $newUrl, $newSp")
}
override fun getRequestURI() = newUri
override fun getRequestURL() = StringBuffer(newUrl)
override fun getServletPath() = newSp
}
/**
* Register the token checker interceptor
*/
@Configuration
@ConditionalOnProperty(
value = ["allnet.server.check-keychip"],
havingValue = "true",
matchIfMissing = false
)
class AllNetSecureInit(
val tokenChecker: TokenChecker,
) : WebMvcConfigurer {
val log = LoggerFactory.getLogger(AllNetSecureInit::class.java)
override fun addInterceptors(reg: InterceptorRegistry) {
log.info("AllNet: Added token interceptor to secure requests.")
reg.addInterceptor(tokenChecker).addPathPatterns("/gs/**")
}
}