java 查找从给定客户端 IP 创建的活动会话数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3679465/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 02:59:20  来源:igfitidea点击:

Find number of active sessions created from a given client IP

javasessionservletsip-address

提问by Somu

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

有没有办法确定从给定客户端 IP 地址创建的活动会话数?

回答by BalusC

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 Stringis the IP address) with and check on every ServletRequestif the HttpSession#isNew()and add it to the Mapalong 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 HttpSessionfrom the Mapduring HttpSessionListener#sessionDestroyed().

标准的 Servlet API 没有为此提供工具。最好你可以做的是保持Map<HttpSession, String>自己(这里String是IP地址),并检查每个ServletRequest如果HttpSession#isNew()并将其添加到Map沿ServletRequest#getRemoteAddr()。然后,您可以使用Collections#frequency()on获取活动会话的 IP 地址数量Map#values()。您只需要确保HttpSessionMapduring 中删除HttpSessionListener#sessionDestroyed()

This all can be done in a single Listenerimplementing the ServletContextListener, HttpSessionListenerand ServletRequestListener.

这一切都可以在单个Listener实现ServletContextListener,HttpSessionListener和 中完成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.xmllike follows:

定义web.xml如下:

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

You can use it in any servlet like follows:

您可以在任何 servlet 中使用它,如下所示:

SessionCounter counter = SessionCounter.getInstance(getServletContext());
int count = counter.getCount("127.0.0.1");

回答by Brimstedt

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):

我需要在没有新部署的情况下快速获取这些信息。可以通过更改 JSP 并添加以下代码段来完成。(只有有活动的会话才会获得值集):

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

Then create a groovy script to query jmx:

然后创建一个groovy脚本来查询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
...

回答by Ellipsis

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

非常好的例子 Balus C。我们通过使用观察者监听器解决了这个问题。这是相同的很好的示例/教程。

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

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

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

只是认为这会对其他游客有所帮助。:)

Edit : *** April 2017 **

编辑:*** 2017 年 4 月 **

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

看起来包含上述来源的http://www.big-oh.net/站点已经死了。是来自 web.archive.org 的来源。还添加了 github gist 中的文件引用网页。Gist源码及其html 预览