开发者

GRAILS: how to get the number of currently signed in users via spring security core plugin?

开发者 https://www.devze.com 2023-03-19 03:07 出处:网络
my problem is, that i want to limit the number of users that can simultaneously be logged inmy application (this value is stored in the database). first i tried to do that with some configuration in t

my problem is, that i want to limit the number of users that can simultaneously be logged in my application (this value is stored in the database). first i tried to do that with some configuration in tomcat or other web containers - but there´s the problem, that a session is used also if a user is not logged in (displaying the login page also needs a session in tomcat)... so i need to check how many users are "really" logged in. i´ve found quite a lot code examples for t开发者_C百科he acegi plugin, but nothing really helpful about the springsecurity core plugin.

my snippets so far:

in resources.groovy i´ve defined my beans:

beans = {
    sessionRegistry(org.springframework.security.concurrent.SessionRegistryImpl)

    concurrentSessionController(org.springframework.security.concurrent.ConcurrentSessionControllerImpl) { 
        sessionRegistry = ref('sessionRegistry') 
        maximumSessions = -1 
   }
}

in BootStrap.groovy the begging of the init is :

class BootStrap {

    def springSecurityService

    def authenticationManager
    def concurrentSessionController
    def securityContextPersistenceFilter

    def init = { servletContext ->
        authenticationManager.sessionController = concurrentSessionController
        ...

and in Config.groovy i´ve added :

grails.plugins.springsecurity.providerNames = ['concurrentSessionController', 'daoAuthenticationProvider', 'anonymousAuthenticationProvider', 'rememberMeAuthenticationProvider'] 

but then as soon as the application starts (grails run-app), it crashes, when it tries to configure the SpringSecury :

...
Running Grails application..

Configuring Spring Security ...
Application context shutting down...
Application context shutdown.
limepix@turbo:~/develop/testproject$

i have configured logging for my application - the content / the last entry in my logfile is:

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)

maybe someone can point me to some docs, examples or can directly tell me, how to get the number of currently signed in users.

greeting from nuremberg, germany

limepix


Thanks for your answer! Now i got it...

The steps i took are:

Defining the beans:

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' 
        } 
} 

then in my controller i injected:

class SystemController {    

    def sessionRegistry

and the check, how many sessions are currently in use:

    def sessioncount = {
        def cnt = 0

        sessionRegistry.getAllPrincipals().each{
            cnt += sessionRegistry.getAllSessions(it, false).size()
        }    

        render cnt
    }

additional steps that must be made:

  1. install templates from grails (grails install-templates)
  2. add listener to web.xml:

    <listener>
        <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
    </listener>
    

and now it works!

great! :)

(now the next steps are - defining an eventlistener (when the user logs in) check the number of licenses(sessions) and permit or deny access to him. but i think that´s not that tricky... we´ll see...)


First I was thinking of counting users which logged in given period, but this can be inaccurate.

I think you could cache user id and time of his last action. Then you could write filter, that on every action updates this cache if user is logged in. Then you could just count items that are in the cache. If your cache would be small, you could also iterate over it and remove users that are inactive for eg. five minutes (or any other, like session expiration - btw: sessionId could also be stored there, so you could check if that session is still valid). If cache big, scheduled job could take care of it.

0

精彩评论

暂无评论...
验证码 换一张
取 消