Grails - 不要为某些请求路径打开hibernate会话

时间:2018-04-16 19:13:14

标签: hibernate spring-boot grails grails3

我们希望为Grails 3应用程序实施API速率限制。我们为此目的使用拦截器和redis。但是,有一个问题是为每个进入Grails的请求打开hibernate会话(打开数据库连接)。这是一种我们不能忽视的资源消耗,因为它可以通过简单的攻击轻松达到MySQL连接限制。

问题是如何强制Grails不为某些url /拦截器打开hibernate会话的最佳方法是什么。我知道像konghq.com这样的API网关,这对我们来说不是一个选择。

我也知道实施GrailsOpenSessionInViewInterceptor的{​​{1}}负责会话管理。那么它是唯一一个覆盖这个拦截器的选项吗?如何为那些符合速率限制的请求打开hibernate会话?

1 个答案:

答案 0 :(得分:0)

最后,我覆盖GrailsOpenSessionInViewInterceptor,只有在满足速率限制的情况下才打开hibernate会话。

import org.grails.web.servlet.mvc.GrailsWebRequest
import org.grails.web.util.GrailsApplicationAttributes
import org.springframework.web.context.request.WebRequest

import javax.servlet.http.HttpServletRequest

class MyOpenSessionInViewInterceptor extends GrailsOpenSessionInViewInterceptor {

    @Override
    void preHandle(WebRequest request) throws DataAccessException {
        GrailsWebRequest grailsRequest = (GrailsWebRequest) request.getAttribute(GrailsApplicationAttributes.WEB_REQUEST,
                WebRequest.SCOPE_REQUEST)
        HttpServletRequest servletRequest = grailsRequest.request

        // intercept /api/* requests
        if (!servletRequest.requestURI.startsWith('/api')) {
            // if rate limits exceeded
            if (checkRateLimits) {
                servletRequest.setAttribute('MY_RATE_LIMITS_EXCEEDED', true)
                return
            }

            super.preHandle(request)
        }
    }
}

别忘了在resource.groovy中注入你的bean。

// Place your Spring DSL code here
beans = {

    // intercept opening of hibernate cache
    openSessionInViewInterceptor(MyOpenSessionInViewInterceptor) {
        hibernateDatastore = ref('hibernateDatastore')
    }
}

我把它与内部grails拦截器放在一起,我从Spring开放会话拦截器检查传递属性。

class V1RateLimitInterceptor {

    V1RateLimitInterceptor() {
        match(namespace: 'api')
    }

    boolean before() {
        // request rate limits
        boolean rateLimit = (boolean) request.getAttribute('MY_RATE_LIMITS_EXCEEDED')
        if (rateLimit) {
            return false
        }

        return true
    }
}

这对我们来说是暂时的解决方案,因为我们将来会使用像konghq.com这样的API网关。