我正在尝试使用Spring创建一个Web应用程序。 webapplication是一个beta / demo网站,仅限邀请。因此,我需要生成一个指向webapplication url的链接,附加一个唯一的id,该ID将在24小时内有效。用户可以使用该链接24小时并使用(我也有通过ip限制用户的计划)
为了实现这样的令牌生成和到期,我应该只依靠具有会话超时时间的容器吗?或者使用令牌创建和到期服务创建弹簧支持的服务层是否有意义?
修改
既然我已经获得了更多的关注,我想我会重新解释这个问题,以便更有意义 - 在一段时间后迫使用户退出Web应用程序的好策略?
答案 0 :(得分:4)
依赖会话超时是不够的。
我不熟悉Spring。对于任何有您要求的Web应用程序,我会将我的通用解决方案如下所示:
假设邀请包含指向Web应用程序的链接。
假设链接包含唯一ID。
假设Beta / Demo用户表具有beta-expiry
(日期时间)列以保存到期日期和时间。
使用邀请中的链接访问您的网络应用程序时,请考虑从那时起24小时更新该unique_id的beta-expiry
列。
当Beta / Demo用户尝试登录时,请检查该特定用户的beta-expiry
列,并在未达到到期时允许访问。在到期时显示适当的消息。
每当签名的Beta / Demo用户执行对您的Web应用程序的后续访问时,请检查该特定用户的beta-expiry
列,并在未达到到期时允许访问。在到期时显示适当的消息。
如果看起来很有用,请显示一个倒数计时器,显示标题区域中某处的左侧时间。
如果所有用户或部分用户都延长了Beta使用率,您可以相应地更新beta_expiry
列。
此外,您还可以使用invitation-expiry
列来保持邀请到期,例如考虑特定的持续时间。发出邀请后48小时。
我们使用一些类似的解决方案在特定的无法访问时间后从我们的SaaS应用程序中注销(登录)用户。
答案 1 :(得分:3)
我认为您应该更多地依赖后端而不是cookie上的会话,想象一下您将cookie设置为24小时到期但客户端从浏览器中删除cookie(取决于您的逻辑) )您的链接将生成新会话,否则请求将被阻止。
恕我直言,您可以在客户端存储会话cookie,但您需要在服务器中有第二个比较源,可能是数据库,no-sql文档,缓存中的集合,您可以比较的内容和检查最新的访问客户端。
只需将所有内容放在一起想象以下用例:
我希望这会有所帮助。 问候
答案 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
方法中采取的步骤来检查用户的有效性:
cacheableService.getUserIdWithExpiryDate(userId)
expiryDateTime.isAfter(currentDateTime)
,请继续处理请求。对于缓存,您可以将Spring Cache Abstraction与EHCACHE一起使用。
答案 3 :(得分:2)
在这里,我可以想到我见过的两个用例。
1。)此类管理用于在线测试或电子邮件验证等应用程序中,向用户提供带有令牌的链接 >。此链接和令牌在某个固定的时间段内有效,并且只能使用一次。 (例如在线测试或密码重置电子邮件)
2。)另一个用例是提供一个令牌的链接,它在一段固定的时间内也有效,但在这种情况下,链接和令牌可以使用任意数量的时间在允许的时间内(例如,测试或某些大学入学的在线注册表格)。
因此,确实只使用会话来管理它不是一个好的选择,因为可以清除浏览器。 因此,您需要在服务器(可能位于数据库中)维护一对链接和令牌以及其他一些信息,例如上次访问时间,创建日期和时间 ,有效至。
为了更灵活的链接有效时间和令牌可以设置不同(例如,链接可以用于一组用户,但令牌对于用户是唯一的。)
因此,您可以在每次用户访问时使用此信息,以检查链接或令牌是否仍然有效以及他们上次访问的时间是多少。如果结果是过期,那么您可以显示相关的错误消息。
答案 4 :(得分:2)
<强>令牌强>
出于这种营销目的,我们会预先生成令牌,将它们与所有信息一起存储在数据库中,例如对某些用户帐户的限制,ip范围(对于某些移动运营商),使用的日期和时间等等。
如果是一个时间码,我们只是将其标记为在数据库中使用。
要生成这些代码,我们使用随机数或编码一些信息并使用(SHA-1或更好)。然后我们使用bigInteger.toString(36)或不同的方案,并将前16个字母分组,使其看起来像许可证密钥。
如果我们用useraccount / name或carrier(mobile)表示信息,或者我们甚至可以在没有数据库的情况下验证令牌。
强制用户退出
只需在用户第一次启动会话或登录时检查令牌的有效性。在整个会话中,您只需检查令牌是否已过期(如果您有一个值,则在会话中存储一个值,附加它(加密) )在网址或其他任何内容或检查数据库。
因此,在每个请求中,您只需检查用户是否有权访问您的网站,否则您将使用错误/信息页面阻止用户。
您还可以为每个页面添加一个java脚本。该脚本可以确定用户使用您网站的权限是否已过期:
一旦java脚本程序注意到令牌已过期,请删除内容部分并用信息/错误页面内容替换它(或将隐藏的div标记为可见)。这样,每次用户重新访问仍然存储在浏览器历史中的页面时也会被破坏。 (如果这对你来说是必要的)。
<强>摘要强>
答案 5 :(得分:1)
24小时后“删除用户帐户”(取决于您构建日志系统的方式)如何? 每次加载页面时,将其与检查用户的帐户相结合,将在24小时阈值通过后的第一次刷新时强迫他/她退出。
答案 6 :(得分:1)
您可以存储带有过期时间的ID,并且当请求带有该ID时检查是否 它仍然有效 如果你想要完成像id这样的事情,那么在第一次请求后5小时就有效,然后在第一次请求时存储时间,并为每个后续请求检查它是否仍然有效