如何在AEM中跨集群环境进行会话管理?

问题描述 投票:0回答:4

考虑以下场景:

我有两个发布服务器来服务调度程序后面的请求,调度程序正在执行一些负载平衡机制,以循环方式在两个服务器之间分发请求。

用例:

用户从登录页面输入登录凭据,然后单击“提交”。调度程序将请求定向到“发布服务器 1”。身份验证成功后,将向客户端提供会话 ID,并将相应的会话信息存储在“Publish 1”上。

用户点击另一个受保护的页面,但调度程序将请求重定向到“发布服务器 2”,该服务器没有与会话 ID 对应的会话信息。

合理的结果: 会话被重置,并提示用户再次登录。

如何处理这样的需求?

注意: 我的用户不在 AEM 中,正在从数据库验证用户的真实性。

P.S.: 我已经去过一些博客,它们说 AEM 不支持 Http Session 集群,但没有一个提供正确的解决方案。

aem httpsession
4个回答
1
投票

一种替代方法是使用网络路由。我们使用负载均衡器,它可以配置为启用粘性会话。它实质上添加了一个 cookie,用于后续请求将用户路由到用户第一次访问的同一发布者。这是一个非 AEM 解决方案,纯粹是网络和负载均衡器的一个功能,因此在您的情况下它可能是也可能不是一个选项。 AEM 调度程序配置还允许

stickyConnections
配置,这听起来像是在网络负载均衡器中完成相同的事情。

另见


1
投票

您可以执行以下操作

  1. 在调度程序和负载均衡器(如果有的话)上启用粘性会话

    #Allowing Sticky sessions
    /stickyConnectionsFor "/content/brand/en-us"
    
  2. 启用会话管理

    #Configuration to increase session timeout limit
    /sessionmanagement
    {
            /directory "/mnt/var/www/html/content/.sessions"
            /header "Cookie:login-token"
            /timeout "3600"
    }
    

    PS: 3600s=60mins


0
投票

两种可能的解决方案-

1)如果外部IDP提供了认证服务,则将认证信息存储在cookie中。无论发布者请求到哪个,它都会使用 cookie 中的信息,并将与 IDP 服务检查会话。

2) 如果使用您的自定义身份验证处理程序,则在调度程序中使用粘性会话,这将确保请求返回到会话处于活动状态的同一发布者。


0
投票

这是个老问题,可以用Redis Cache之类的东西解决。 Redis是内存数据库中的键值对。它就像地图或一个非常大的 JSON 文档。 这种方法不需要粘性连接。

您可以将数据保存在 Redis 中,而不是将数据保存在 Session 中。 例如。 Key=JSESSIONID OR A CUSTOM COOKIE and value=YourObject(你当前保存在会话中) 所以关键是你的发布实例会将会话数据保存到 redis 中并从 redis 本身获取。

BinaryJedis jedis = RedisUtility.getJedisInstance();
        
        Customer customer = new Customer();
        customer.setFirstName(request.getParameter("firstName"));
        customer.setLastName(request.getParameter("lastName"));
        customer.setCustomerId(request.getParameter("customerId"));
        String jSessionId = request.getCookie("JSESSIONID").getValue();
        
        byte[] value = RedisUtility.serialize(customer);
          
        jedis.set(jSessionId.getBytes(), value);
        
        
        response.setContentType("application/json");
        PrintWriter writer = response.getWriter();
        writer.print("{'success':'true'}");

Redis 实用程序

public final class RedisUtility {

private static BinaryJedis bJedis;

public static synchronized BinaryJedis getJedisInstance() {
    if (bJedis == null) {
        bJedis = new BinaryJedis("localhost",6379);
    }
    return bJedis;
}
public static byte[] serialize(Serializable obj) {
    return SerializationUtils.serialize(obj);
}

public static Object deserialize(byte[] bytes) throws ClassNotFoundException, IOException {
    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
    Object object = ois.readObject();
    return object;
}

}

从 Redis 中获取值

try {
        BinaryJedis jedis = RedisUtility.getJedisInstance();
        String jSessionId = req.getCookie("JSESSIONID").getValue();
        logger.info("JSESSONID {}",jSessionId);
        byte[] value =jedis.get(jSessionId.getBytes());
        logger.info("Value from Redis {}",value);
        if(value!=null) {
            Customer cust = (Customer) RedisUtility.deserialize(value);
            Gson gson = new Gson();
            resp.getWriter().write(gson.toJson(cust));
            return;
        }
        
    }
© www.soinside.com 2019 - 2024. All rights reserved.