我的问题是,我想限制可以同时在我的应用程序中记录的用户数量(此值存储在数据库中)。首先我尝试使用tomcat或其他Web容器中的某些配置来做到这一点 - 但是有问题,如果用户没有登录也会使用会话(显示登录页面也需要tomcat中的会话)。所以我需要检查有多少用户“真正”登录。 我已经为acegi插件找到了很多代码示例,但对springsecurity核心插件没有任何帮助。
到目前为止我的摘要:
在resources.groovy我定义了我的bean:
beans = {
sessionRegistry(org.springframework.security.concurrent.SessionRegistryImpl)
concurrentSessionController(org.springframework.security.concurrent.ConcurrentSessionControllerImpl) {
sessionRegistry = ref('sessionRegistry')
maximumSessions = -1
}
}
在BootStrap.groovy中,init的乞讨是:
class BootStrap {
def springSecurityService
def authenticationManager
def concurrentSessionController
def securityContextPersistenceFilter
def init = { servletContext ->
authenticationManager.sessionController = concurrentSessionController
...
在Config.groovy中我添加了:
grails.plugins.springsecurity.providerNames = ['concurrentSessionController', 'daoAuthenticationProvider', 'anonymousAuthenticationProvider', 'rememberMeAuthenticationProvider']
但是一旦应用程序启动(grails run-app),它会在尝试配置SpringSecury时崩溃:
...
Running Grails application..
Configuring Spring Security ...
Application context shutting down...
Application context shutdown.
limepix@turbo:~/develop/testproject$
我为我的应用程序配置了日志记录 - 我的日志文件中的内容/最后一个条目是:
2011-07-11 11:19:43,071 [main] ERROR context.GrailsContextLoader - Error executing bootstraps: No bean named 'concurrentSessionController' is defined
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'concurrentSessionController' is defined
at SpringSecurityCoreGrailsPlugin$_createBeanList_closure22.doCall(SpringSecurityCoreGrailsPlugin.groovy:648)
at SpringSecurityCoreGrailsPlugin.createBeanList(SpringSecurityCoreGrailsPlugin.groovy:648)
at SpringSecurityCoreGrailsPlugin.this$2$createBeanList(SpringSecurityCoreGrailsPlugin.groovy)
at SpringSecurityCoreGrailsPlugin$_closure4.doCall(SpringSecurityCoreGrailsPlugin.groovy:581)
at org.grails.tomcat.TomcatServer.start(TomcatServer.groovy:212)
at grails.web.container.EmbeddableServer$start.call(Unknown Source)
at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy:158)
at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy)
at _GrailsSettings_groovy$_run_closure10.doCall(_GrailsSettings_groovy:280)
at _GrailsSettings_groovy$_run_closure10.call(_GrailsSettings_groovy)
at _GrailsRun_groovy$_run_closure5.doCall(_GrailsRun_groovy:149)
at _GrailsRun_groovy$_run_closure5.call(_GrailsRun_groovy)
at _GrailsRun_groovy.runInline(_GrailsRun_groovy:116)
at _GrailsRun_groovy.this$4$runInline(_GrailsRun_groovy)
at _GrailsRun_groovy$_run_closure1.doCall(_GrailsRun_groovy:59)
at RunApp$_run_closure1.doCall(RunApp.groovy:33)
at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:427)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:415)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.executeTargets(Gant.groovy:590)
at gant.Gant.executeTargets(Gant.groovy:589)
也许有人可以指点我一些文档,示例或者可以直接告诉我,如何获取当前已登录用户的数量。
来自德国纽伦堡的问候limepix
答案 0 :(得分:4)
感谢您的回答!现在我明白了......
我采取的步骤是:
定义bean:
import org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy
import org.springframework.security.web.session.ConcurrentSessionFilter
import org.springframework.security.core.session.SessionRegistryImpl
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
beans = {
sessionRegistry(SessionRegistryImpl)
sessionAuthenticationStrategy(ConcurrentSessionControlStrategy, sessionRegistry) {
maximumSessions = -1
}
concurrentSessionFilter(ConcurrentSessionFilter){
sessionRegistry = sessionRegistry
expiredUrl = '/login/concurrentSession'
}
}
然后在我的控制器中我注入了:
class SystemController {
def sessionRegistry
并检查当前正在使用的会话数量:
def sessioncount = {
def cnt = 0
sessionRegistry.getAllPrincipals().each{
cnt += sessionRegistry.getAllSessions(it, false).size()
}
render cnt
}
必须采取的其他步骤:
将侦听器添加到web.xml:
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
现在它有效!
太棒了! :)
(现在接下来的步骤是 - 定义一个eventlistener(当用户登录时)检查许可证(会话)的数量并允许或拒绝访问他。但我认为这不是那么棘手......我们我会看......)
答案 1 :(得分:1)
首先,我考虑计算在给定时间段内登录的用户,但这可能是不准确的。
我认为您可以缓存用户ID和上次操作的时间。然后您可以编写过滤器,如果用户已登录,则每次操作都会更新此缓存。然后您可以只计算缓存中的项目。如果您的缓存很小,您也可以迭代它并删除不活动的用户,例如。五分钟(或任何其他,如会话到期 - 顺便说一句:sessionId
也可以存储在那里,因此您可以检查该会话是否仍然有效)。如果缓存很大,预定的工作可以处理它。