Find number of active sessions created from a given client IP

前端 未结 3 1198
星月不相逢
星月不相逢 2020-12-03 00:29

Is there a way to determine the number of active sessions created from a given client IP address?

相关标签:
3条回答
  • 2020-12-03 00:49

    The standard Servlet API doesn't offer facilities for that. Best what you can do is to maintain a Map<HttpSession, String> yourself (where the String is the IP address) with and check on every ServletRequest if the HttpSession#isNew() and add it to the Map along with ServletRequest#getRemoteAddr(). Then you can get the amount of IP addresses with an active session using Collections#frequency() on Map#values(). You only need to ensure that you remove the HttpSession from the Map during HttpSessionListener#sessionDestroyed().

    This all can be done in a single Listener implementing the ServletContextListener, HttpSessionListener and ServletRequestListener.

    Here's a kickoff example:

    public class SessionCounter implements ServletContextListener, HttpSessionListener, ServletRequestListener {
    
        private static final String ATTRIBUTE_NAME = "com.example.SessionCounter";
        private Map<HttpSession, String> sessions = new ConcurrentHashMap<HttpSession, String>();
    
        @Override
        public void contextInitialized(ServletContextEvent event) {
            event.getServletContext().setAttribute(ATTRIBUTE_NAME, this);
        }
    
        @Override
        public void requestInitialized(ServletRequestEvent event) {
            HttpServletRequest request = (HttpServletRequest) event.getServletRequest();
            HttpSession session = request.getSession();
            if (session.isNew()) {
                sessions.put(session, request.getRemoteAddr());
            }
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent event) {
            sessions.remove(event.getSession());
        }
    
        @Override
        public void sessionCreated(HttpSessionEvent event) {
            // NOOP. Useless since we can't obtain IP here.
        }
    
        @Override
        public void requestDestroyed(ServletRequestEvent event) {
            // NOOP. No logic needed.
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent event) {
            // NOOP. No logic needed. Maybe some future cleanup?
        }
    
        public static SessionCounter getInstance(ServletContext context) {
            return (SessionCounter) context.getAttribute(ATTRIBUTE_NAME);
        }
    
        public int getCount(String remoteAddr) {
            return Collections.frequency(sessions.values(), remoteAddr);
        }
    
    }
    

    Define it in web.xml like follows:

    <listener>
        <listener-class>com.example.SessionCounter</listener-class>
    </listener>
    

    You can use it in any servlet like follows:

    SessionCounter counter = SessionCounter.getInstance(getServletContext());
    int count = counter.getCount("127.0.0.1");
    
    0 讨论(0)
  • 2020-12-03 00:49

    Very nice example Balus C. We solved this problem by using an Observer Listener. Here is nice example/tutorial for the same.

    http://www.big-oh.net/BigOhSoftwareWeb/content/tutorials/requestObserverListener.jsp

    Just thought it will be helpful to other visitors. :)

    Edit : *** April 2017 **

    Looks like the http://www.big-oh.net/ site that contains the source above is dead. Here is the source from web.archive.org. Also the added the file referred webpage in github gist. Gist source and its html preview

    0 讨论(0)
  • 2020-12-03 00:59

    I needed to get this information quickly without new deploys. It can be done by altering JSP and add the following snippet. (Only sessions with activity will get the value set):

    <%
     // Set user agent and ip in session
     session.setAttribute("agent", request.getHeader("user-agent") + "@" + request.getRemoteAddr());
    %>
    

    Then create a groovy script to query jmx:

    import javax.management.remote.*
    import javax.management.*
    import groovy.jmx.builder.*
    
    // Setup JMX connection.
    def connection = new JmxBuilder().client(port: 4934, host: '192.168.10.6')
    connection.connect()
    
    // Get the MBeanServer.
    def mbeans = connection.MBeanServerConnection
    
    def mbean = new GroovyMBean(mbeans, 'Catalina:type=Manager,host=localhost,context=/')
    println "Active sessions: " + mbean['activeSessions']
    
    def sessions = mbean.listSessionIds().tokenize(' ');
    
    def ips = [:];
    def agents = [:];
    
    sessions.each
    {
        def agentString = mbean.getSessionAttribute(it, "agent");
        if(agentString != null)
        {
            agent = agentString.tokenize('@');
        }
        else
        {   
            agent = ['unknown', 'unknown'];
        }
    
        if(agents[agent[0]] == null)
        {
            agents[agent[0]] = [];
        }
        agents[agent[0]] += [it];
    
        if(ips[agent[1]] == null)
        {
            ips[agent[1]] = [];
        }
        ips[agent[1]] += it;
    
    
    };
    
    println "Ips"
    ips = ips.sort { -it.value.size }
    ips.each
    {
        ip, list ->
        println "${ip}\t${list.value.size}";
        //println list;
        //println "";
    }
    
    println ""
    println "Agents"
    agents = agents.sort { -it.value.size }
    agents.each
    {
        agent, list ->
        println "${agent}\t${agents[agent].size}";
        //println list;
        //println "";
    }
    

    Result

    Active sessions: 729
    Ips
    unknown 102
    68.180.230.118  11
    80.213.88.107   11
    157.55.39.127   9
    81.191.247.166  2
    ...
    
    Agents
    Mozilla/5.0 (compatible; MJ12bot/v1.4.5; http://www.majestic12.co.uk/bot.php?+) 117
    unknown 102
    Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) 55
    Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp) 29
    ...
    
    0 讨论(0)
提交回复
热议问题