【问题标题】:getting online users using JWT tokens使用 JWT 令牌获取在线用户
【发布时间】:2021-10-14 23:02:25
【问题描述】:

我想创建一个返回在线用户列表的服务。用户使用 JWT 令牌登录 - 但我不确定如何获取在线用户 - 或/并返回用户列表但指出他们是否在线。

我是否必须在 mongodb 中存储已登录/注销的会话令牌/电子邮件 - 如果他们不注销怎么办?

我当前的代码如下所示

@CrossOrigin
@GetMapping("/api/getActiveUsers")
public ResponseEntity<Object> activeUser(HttpServletRequest request) {
    TokenManagement user = new TokenManagement();
    try {
        // return the user authenticate
        HttpSession session = request.getSession(true);
        List<Object> userListHttp = (List<Object>) Arrays.asList(session.getAttribute("user"));
        // alternative way for get user logged
        List<String> userList = getUsersFromSessionRegistry();
        return ResponseEntity.ok().body(userListHttp); 
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
}


public List<String> getUsersFromSessionRegistry() {
    return sessionRegistry.getAllPrincipals()
            .stream()
            .filter((u) -> !sessionRegistry.getAllSessions(u, false)
            .isEmpty())
            .map(o -> {
                if (o instanceof Person) {
                    return ((Person) o).getEmail();
                } else {
                    return o.toString();
                }
            }).collect(Collectors.toList());
}

【问题讨论】:

  • 不,您不能存储会话令牌。相反,您可以存储一个“logged_in_until”,它只包含一个时间戳,其值与 jwt 的到期时间相同,每当更新 jwt 时都会更新,如果用户注销则清除。未注销的用户即使关闭浏览器、关闭计算机等仍处于登录状态。
  • 所以如果登录用户显示 - api 活动,可能会指示用户在线布尔值?

标签: java spring-boot jwt


【解决方案1】:

您可以从过期的 JWT 中提取用户。

然后您可以使用缓存(例如考虑 Redis)将用户存储在 JWT 过期时自动过期的记录中。

如果用户明确退出,只需从缓存中删除该用户。

所以要统计用户,你只需要统计缓存中的项目。

这并不意味着如果客户端出现错误并在没有明确注销的情况下断开连接,您将在登录的用户编号上出现错误,但缓存到期可以缓解这种情况

我建议使用 Redis 而不是本地缓存,因为如果您处于具有多个微服务实例的微服务环境中,它也可以工作,因为登录的用户存储在所有微服务实例通用的外部缓存中


您可以使用Filter 拦截所有 HTTP 传入请求:

过滤器是一个对象,它对资源的请求(servlet 或静态内容)或来自资源的响应或两者都执行过滤任务。

public class SessionFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        HttpServletRequest req = (HttpServletRequest) request;
        String bearer = req.getHeader("authorization");
        String jwt = bearer.substring(7); // Remove Beared at the beginning 
        String username = extractUsername(jwt);
        Date expiringDate = extractExpiring(jwt);
        insertInCache(username, expiringDate);
        chain.doFilter(request, response);
    }

   ...

    private String extractUsername(String jwt) {
        // Use libraries to extract the username from the jwt 
    }

    private Date extractExpiring(String jwt) {
        // Use libraries to extract the expiring from the jwt 
    }

    private void insertInCache(String username, Date expiringDate) {
        // Insert username in the cache with automatic expiring
    }
    

}

此代码将拦截所有传入的请求,提取令牌,解析它并将用户插入缓存中。考虑使用任何 java 库从 JWT 中提取信息以创建方法 extractUsername 和 extractExpiring。

此代码只是编程的基本代码。你需要完成它:

  • 管理未经身份验证的请求
  • 管理显式注销(在控制器中)
  • 添加一种方法来统计查询缓存的用户数(在控制器中)

【讨论】:

  • 这个代码会是什么样子?我只能看到用于创建令牌的 JWT?然后将其存储在 HttpSession 会话中?
  • 我更新答案给你看伪代码
猜你喜欢
  • 2019-11-07
  • 2016-07-18
  • 2019-06-22
  • 1970-01-01
  • 2017-10-21
  • 2021-12-29
  • 1970-01-01
相关资源
最近更新 更多