使用 JWT 的移动身份验证

Posted

技术标签:

【中文标题】使用 JWT 的移动身份验证【英文标题】:Mobile authentication using JWT 【发布时间】:2020-07-25 20:35:10 【问题描述】:

我需要对与 REST api 通信的移动应用程序的用户进行身份验证。

经过一番研究,我发现了两种方法:

    Firebase 身份验证(否,因为我有自己的数据库) JWT 的使用

所以我对 JWT 有疑问:

如果我使用 HTTPS 连接,有人可以窃取令牌吗?(例如中间没有人)

API 必须为每个请求发送一个新令牌?(这样我可以减少令牌的生命周期?)。

为了避免用户重新连接,我需要使用刷新令牌,可以是另一个JWT吗?

【问题讨论】:

【参考方案1】:
    视情况而定,如果您将其存储在本地存储或会话存储中,则可以通过 xss 攻击窃取它。如果您存储在 httpOnly 安全 cookie 上,那就更难了。 但是当你使用 https 时,不可能从请求中窃取它。 不,有一个令牌有效时间,例如 1 小时、1 天等... 是的。它应该是另一个令牌,它被称为刷新令牌,你可以 在此处阅读更多信息: https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/

【讨论】:

1.对于移动应用程序,我认为它只是一个本地存储(例如:android 上的 sharedPreference ),如果我对 HTTPS 理解得很好,则在通信过程中不会发生泄漏。 2.我必须重新发送一个它会过期还是让它过期并发送一个带有刷新令牌的新令牌? 3.如果刷新令牌被窃取,小偷可以生成无限访问令牌?【参考方案2】:

因为您使用的是自己的数据库,所以 JWT 是您的最佳选择。

1- 如果我使用 HTTPS 连接,有人可以窃取令牌吗?:- 是的,他们可以窃取令牌,mitma 是可能的,但即使他们会修改令牌,您的服务器也会通过验证令牌并验证令牌的颁发者来了解(您的客户端和服务器可以使用私钥来加密在客户端响应并在服务器端解密和验证)

2- API 必须为每个请求发送一个新令牌? (这样我可以减少令牌的生命周期?)。 是的,每个令牌都会有所不同,JWT 令牌是您的帖子数据和发行者、主题和其他附加数据的加密形式。所以如果你的post数据每次都不一样,token也会不一样。

3-为了避免用户重新连接,我需要使用刷新令牌,可以是另一个JWT吗? 不需要另一个 JWT。

您可以使用 Jawa JWT 库:- 访问 https://github.com/auth0/java-jwt

并使用这个类来创建、验证和解码 JWT 令牌。

public class JWTTokenVerifier 

public String CreateToken(String body) 
    String token = "";
    try 
        Algorithm algorithm = Algorithm.HMAC256(Constants.APP_SECRET);
        token = JWT.create()
                .withClaim("body", body)
                .withIssuer("auth0")
                .sign(algorithm);
     catch (JWTCreationException exception) 
        //Invalid Signing configuration / Couldn't convert Claims.
        exception.printStackTrace();
    

    System.out.println("TOKEN IS > " + token);
    return token;


public void verifyTokenAndDecodeResponse(String token) 
    try 
        Algorithm algorithm = Algorithm.HMAC256(Constants.APP_SECRET);
        JWTVerifier verifier = JWT.require(algorithm)
                .build(); //Reusable verifier instance
        DecodedJWT jwt = verifier.verify(token);
        String payload = jwt.getPayload();
        Base64 base64Url = new Base64(true);
        payload=new String(base64Url.decode(payload));
        System.out.println("payload is " + payload);
     catch (JWTVerificationException exception) 
        System.out.printf("Unable to parse token");
        exception.printStackTrace();
    
 

【讨论】:

1.如果我在移动应用程序上使用私钥,apk 的逆向工程允许找到密钥吗? (如何考虑 HTTPS 的 mitm ?) 2.如果我的有效负载与消息列表一样大,我们可以发送一个大的 jwt 吗? 3. 感谢代码示例 1.您可以使用 android 签名密钥哈希作为私钥,也可以将其保存在 firebase 在运行时获取它,有很多可用的选项,并且 mitm 是可能的,因为攻击者可以在应用层的 https 层之前嗅探它,我遇到过类似的情况问题也根植设备是一个大问题。 2- 是的,您可以发送大量有效载荷。 有了这个解决方案,如果我需要将与我的客户端关联的密钥存储在数据库中,我会失去 JWT 的优势吗?根据您的经验,最好的身份验证系统是什么? HTTPS + JWT(访问和刷新令牌)是否足够还是我忘记了什么? 首先,您不需要为每个客户端存储私钥。每个客户端和服务器都将使用一个唯一的私钥。是的,HTTPS + JWT 就够了。 您能否确认这个答案,请:我生成一个密钥并存储在移动应用程序和服务器端。我的客户端使用密钥向身份验证服务器发送凭据邮件 +pwd,身份验证使用相同的密钥响应访问令牌 + 刷新令牌(但 JWT 的标志使用仅存储在服务器端的其他秘密)。客户端获取令牌并用于从 REST api 获取资源?所有这些都使用 HTTPS 通道。 (另一个答案是只使用没有私钥的 HTTPS + JWT)

以上是关于使用 JWT 的移动身份验证的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring 和 JWT 进行基于令牌的身份验证

使用 JWT 进行 Laravel API 身份验证

使用 JWT 身份验证与用户合作的正确方法是啥?

这种基于 JWT 的身份验证方法安全吗?

Auth0 NodeJS JWT 身份验证在移动应用程序的 API 中

移动和 Web 应用程序的 Identity Server3 身份验证