管理beta Web应用程序会话的好策略是什么?

时间:2013-09-19 18:30:39

标签: java architecture

我正在尝试使用Spring创建一个Web应用程序。 webapplication是一个beta / demo网站,仅限邀请。因此,我需要生成一个指向webapplication url的链接,附加一个唯一的id,该ID将在24小时内有效。用户可以使用该链接24小时并使用(我也有通过ip限制用户的计划)

为了实现这样的令牌生成和到期,我应该只依靠具有会话超时时间的容器吗?或者使用令牌创建和到期服务创建弹簧支持的服务层是否有意义?

修改

既然我已经获得了更多的关注,我想我会重新解释这个问题,以便更有意义 - 在一段时间后迫使用户退出Web应用程序的好策略?

7 个答案:

答案 0 :(得分:4)

依赖会话超时是不够的。

我不熟悉Spring。对于任何有您要求的Web应用程序,我会将我的通用解决方案如下所示:

  1. 假设邀请包含指向Web应用程序的链接。

  2. 假设链接包含唯一ID。

  3. 假设Beta / Demo用户表具有beta-expiry(日期时间)列以保存到期日期和时间。

  4. 使用邀请中的链接访问您的网络应用程序时,请考虑从那时起24小时更新该unique_id的beta-expiry列。

  5. 当Beta / Demo用户尝试登录时,请检查该特定用户的beta-expiry列,并在未达到到期时允许访问。在到期时显示适当的消息。

  6. 每当签名的Beta / Demo用户执行对您的Web应用程序的后续访问时,请检查该特定用户的beta-expiry列,并在未达到到期时允许访问。在到期时显示适当的消息。

  7. 如果看起来很有用,请显示一个倒数计时器,显示标题区域中某处的左侧时间。

  8. 如果所有用户或部分用户都延长了Beta使用率,您可以相应地更新beta_expiry列。

  9. 此外,您还可以使用invitation-expiry列来保持邀请到期,例如考虑特定的持续时间。发出邀请后48小时。

  10.   

    我们使用一些类似的解决方案在特定的无法访问时间后从我们的SaaS应用程序中注销(登录)用户。

答案 1 :(得分:3)

我认为您应该更多地依赖后端而不是cookie上的会话,想象一下您将cookie设置为24小时到期但客户端从浏览器中删除cookie(取决于您的逻辑) )您的链接将生成新会话,否则请求将被阻止。

恕我直言,您可以在客户端存储会话cookie,但您需要在服务器中有第二个比较源,可能是数据库,no-sql文档,缓存中的集合,您可以比较的内容和检查最新的访问客户端。

只需将所有内容放在一起想象以下用例:

  • 用户获取邀请链接并单击
  • 系统检查他们是否第一次登录系统,并将该日期保存为“开始日期”,将另一个日期保存为“上次访问”
  • 系统设置24小时到期的身份验证Cookie
  • 系统跟踪每个回发/ ajax调用服务器并更新“上次访问”日期
  • 如果用户删除了cookie,系统会检查“上次访问”并与当前服务器日期进行比较
  • 如果有效,系统会使用剩余时间创建新的身份验证Cookie
  • 如果无效,系统会向用户发送消息。
  • 对于用户,cookie将根据剩余时间(开始日期和上次访问之间的计算)到期

我希望这会有所帮助。 问候

答案 2 :(得分:3)

一种策略是通过将相关数据存储在数据库中并使用缓存库(在检查到期日期时减少数据库命中)来跟踪所有用户的expiry date-time。这是一个小例子:

创建一个包含列的数据库表,将用户ID映射到到期日期:id, unique_user_id, expiry_date_time。您需要在代码中创建唯一的用户ID,并在将URL发送给具有此ID的用户之前将其保存在DB中。您可以将null作为expiry_date_time的初始值。创建一个类来表示Java中的这个映射:

class UserIdWithExpiryDate{
        private String userId;
        private Date expiryDateTime;
        ...
}

使用Service方法定义cacheable,该方法将为给定的userId返回此实例:

public interface CacheableService {
    @Cacheable("expiryDates")
    public UserIdWithExpiryDate getUserIdWithExpiryDate(String id);

    public void updateUserIdWithExpiryDate(String userId);
}

import org.joda.time.DateTime;
@Service
public class CacheableServiceImpl implements CacheableService {

    @Autowired
    private YourDao dao;

    @Override
    public UserIdWithExpiryDate getUserIdWithExpiryDate(String id) {
        return dao.getUserIdWithExpiryDate(id);
    }

    public void updateUserIdWithExpiryDate(String userId){
        Date expiryDate = new Date(new DateTime().plusHours(24).getMillis());
        dao.update(userId, expiryDate);
    }
}

getUserIdWithExpiryDate方法的结果存储在缓存中,因此在后续调用(使用相同的参数)时,将返回缓存中的值,而不必实际执行该方法。

下一步是在访问网站时检查用户的到期日期。这可以使用OncePerRequestFilter

完成
@Component("timeoutFilter")
public class TimeoutFilter extends OncePerRequestFilter {

    @Autowired
    CacheableService cacheableService;
    // Here you need to decide whether to proceed with the request or not
    @Override
    protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        filterChain.doFilter(request, response);
    }

}

可以在doFilterInternal方法中采取的步骤来检查用户的有效性:

  1. 从请求中获取用户ID
  2. 执行:cacheableService.getUserIdWithExpiryDate(userId)
  3. 如果第2步返回null,则不存在此ID的用户。您不应该继续请求。
  4. 如果第2步返回UserIdWithExpiryDate的实例,请检查“expiryDateTime”的值
  5. 如果“expiryDateTime”的值为null,则表示用户第一次访问该站点。更新“userExpiryDate”:cacheableService.updateUserIdWithExpiryDate(userId)并继续请求。
  6. 如果“expiryDateTime”不为null,请将其与当前date_time进行比较。如果是expiryDateTime.isAfter(currentDateTime),请继续处理请求。
  7. 对于缓存,您可以将Spring Cache AbstractionEHCACHE一起使用。

答案 3 :(得分:2)

在这里,我可以想到我见过的两个用例。

1。)此类管理用于在线测试或电子邮件验证等应用程序中,向用户提供带有令牌链接 >。此链接和令牌在某个固定的时间段内有效,并且只能使用一次。 (例如在线测试或密码重置电子邮件)

2。)另一个用例是提供一个令牌的链接,它在一段固定的时间内也有效,但在这种情况下,链接和令牌可以使用任意数量的时间在允许的时间内(例如,测试或某些大学入学的在线注册表格)。

因此,确实只使用会话来管理它不是一个好的选择,因为可以清除浏览器。 因此,您需要在服务器(可能位于数据库中)维护一对链接和令牌以及其他一些信息,例如上次访问时间创建日期和时间有效至

为了更灵活的链接有效时间和令牌可以设置不同(例如,链接可以用于一组用户,但令牌对于用户是唯一的。)

因此,您可以在每次用户访问时使用此信息,以检查链接或令牌是否仍然有效以及他们上次访问的时间是多少。如果结果是过期,那么您可以显示相关的错误消息。

答案 4 :(得分:2)

<强>令牌

出于这种营销目的,我们会预先生成令牌,将它们与所有信息一起存储在数据库中,例如对某些用户帐户的限制,ip范围(对于某些移动运营商),使用的日期和时间等等。

如果是一个时间码,我们只是将其标记为在数据库中使用。

要生成这些代码,我们使用随机数或编码一些信息并使用(SHA-1或更好)。然后我们使用bigInteger.toString(36)或不同的方案,并将前16个字母分组,使其看起来像许可证密钥。

如果我们用useraccount / name或carrier(mobile)表示信息,或者我们甚至可以在没有数据库的情况下验证令牌。

强制用户退出

只需在用户第一次启动会话或登录时检查令牌的有效性。在整个会话中,您只需检查令牌是否已过期(如果您有一个值,则在会话中存储一个值,附加它(加密) )在网址或其他任何内容或检查数据库。

因此,在每个请求中,您只需检查用户是否有权访问您的网站,否则您将使用错误/信息页面阻止用户。

您还可以为每个页面添加一个java脚本。该脚本可以确定用户使用您网站的权限是否已过期:

  • 加密令牌在隐藏div中的有效时间,并使用用户本地时间计算绝对时间。然后将绝对过期时间与用户时间进行比较,每次比较(比如每3秒),你可以自己进行所有轮询和推送(彗星,ajax,websockets)行为。

一旦java脚本程序注意到令牌已过期,请删除内容部分并用信息/错误页面内容替换它(或将隐藏的div标记为可见)。这样,每次用户重新访问仍然存储在浏览器历史中的页面时也会被破坏。 (如果这对你来说是必要的)。

<强>摘要

  • 使用随机令牌和数据库或加密信息(如令牌可以使用的那天)和SHA-1。
  • 每次用户请求页面时检查令牌的有效性(将时间段存储在会话/网址中以保存往返数据库)
  • 提供一个java脚本,在重新访问时销毁历史记录中的本地页面。

答案 5 :(得分:1)

24小时后“删除用户帐户”(取决于您构建日志系统的方式)如何? 每次加载页面时,将其与检查用户的帐户相结合,将在24小时阈值通过后的第一次刷新时强迫他/她退出。

答案 6 :(得分:1)

您可以存储带有过期时间的ID,并且当请求带有该ID时检查是否 它仍然有效 如果你想要完成像id这样的事情,那么在第一次请求后5小时就有效,然后在第一次请求时存储时间,并为每个后续请求检查它是否仍然有效