Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rest 使用JWT在多个设备上强制用户注销_Rest_Authentication_Jwt - Fatal编程技术网

Rest 使用JWT在多个设备上强制用户注销

Rest 使用JWT在多个设备上强制用户注销,rest,authentication,jwt,Rest,Authentication,Jwt,我们有一个现有的RESTAPI,目前正在使用JWT 客户端要求用户一次只能使用一台设备。例如,如果用户从iOS设备登录,然后登录Android设备,则应“强制”该iOS设备注销 因为我们使用的是JWT,所以除了用户单击注销时的令牌黑名单外,我们不跟踪令牌 我研究了如何“强制”用户注销,似乎我们需要跟踪用户使用的最后一个令牌,然后在检测到新的登录后使其失效 没有更干净/替代的方法来实现上述目标吗?假设您使用JWT作为承载令牌,根据您的要求,它可能不足以“跟踪用户使用的最后一个令牌,然后在检测到新登

我们有一个现有的RESTAPI,目前正在使用JWT

客户端要求用户一次只能使用一台设备。例如,如果用户从iOS设备登录,然后登录Android设备,则应“强制”该iOS设备注销

因为我们使用的是JWT,所以除了用户单击注销时的令牌黑名单外,我们不跟踪令牌

我研究了如何“强制”用户注销,似乎我们需要跟踪用户使用的最后一个令牌,然后在检测到新的登录后使其失效


没有更干净/替代的方法来实现上述目标吗?

假设您使用JWT作为承载令牌,根据您的要求,它可能不足以“跟踪用户使用的最后一个令牌,然后在检测到新登录后使其失效。”

当客户机发送承载令牌(独立于它是否是JWT)时,客户机也知道令牌,这允许发送方也将令牌从一个设备复制和粘贴到另一个设备(或发出包括来自不同设备的相同令牌的请求)


您的需求听起来像是适当会话管理的标准用例,例如允许用户代理绑定

以下是实现您的需求的步骤:

步骤1:保存为更新密码或从所有设备注销而执行的上次用户活动的时间戳

  • 添加列
    lastSessionResetDate
    以在用户表中存储上次密码更新日期

  • 执行忘记密码/更改密码API或从所有设备注销时,更新
    lastSessionResetDate

  • 步骤2:在生成JWT令牌时,在JWT声明中设置
    lastSessionResetDate

    生成令牌时设置声明的示例

    //make a claims map (`Claim extends Map<String, Object>`)
    Map<String, Object> claims = new HashMap<>();
            claims.put(CLAIM_KEY_USERNAME, user.getUserName());
            claims.put(CLAIM_KEY_AUDIENCE, "web");
            claims.put(CLAIM_KEY_CREATED, new Date());
            claims.put(CLAIM_KEY_LAST_SESSION_RESET, user.lastSessionResetDate());
    
    //set claims and build JWT
    return Jwts.builder().setClaims(claims).setSubject(user.getUserName())
    .setIssuedAt(new Date(System.currentTimeMillis()))
    .setExpiration(new Date(System.currentTimeMillis() + yourTokenValidity))
    .signWith(SignatureAlgorithm.HS512,"yourSecretEncodedBase64")
    .compact();
    
    //制作索赔映射(`Claim extends map`)
    Map claims=newhashmap();
    claims.put(claims_KEY_USERNAME,user.getUserName());
    声明。声明(声明、关键、受众,“网络”);
    claims.put(claims_KEY_CREATED,new Date());
    claims.put(claims\u KEY\u LAST\u SESSION\u RESET,user.lastSessionResetDate());
    //设置声明并构建JWT
    返回Jwts.builder().setClaims(claims).setSubject(user.getUserName())
    .setIssuedAt(新日期(System.currentTimeMillis()))
    .setExpiration(新日期(System.currentTimeMillis()+yourTokenValidity))
    .signWith(SignatureAlgorithm.HS512,“yourSecretEncodedBase64”)
    .compact();
    
    您可以在解析JWT令牌时获得任何声明值

    步骤3:验证用户和会话的时间 JWT获取用户实体后,检查
    lastSessionResetDate
    是否有效到时间,否则请求将被授权。 您必须已经从数据库中提取用户,所以不需要进行任何其他查询,因为我们新添加的列
    lastSessionResetDate
    将是同一查询结果的一部分。(只需添加一个if-else块)

    注意:您还可以从用户那里获得从其他设备注销的提示值

    希望你有一个想法,快乐编码