如何在 Android 上从 JWT 收集签名、标头和正文
Posted
技术标签:
【中文标题】如何在 Android 上从 JWT 收集签名、标头和正文【英文标题】:How to collect the signature, header and body from JWT on Android 【发布时间】:2016-10-14 20:19:45 【问题描述】:我最近了解了 Json Web Token (JWT)。因为我喜欢它的工作方式,所以我开始在我的项目中实施它。我的项目涉及两个应用程序进行通信。一个是安卓应用,另一个是 Laravel Web 应用。
在服务器端验证用户凭据后,移动应用程序登录。
我已将用户名和密码从移动应用程序发送到服务器,并且我已获得字符串格式的 JWT。但从那时起,我找不到收集 JWT 内容的方法。
我已经浏览了几乎所有可能显示的结果(谷歌搜索结果),但我无法获得内容、签名和标题。
我进一步了解的一种方法是使用以下代码,请注意我已删除 setSigningKey():
try
Claims claims = Jwts.parser().parseClaimsJwt(jwtHeaderAndClaim).getBody();
System.out.println("ID of the claims: " + claims.getId().toString());
catch (Exception e)
Log.e("Exception: ", e.toString());
以上代码产生如下错误:
Exception: io.jsonwebtoken.PrematureJwtException: JWT must not be accepted before 2016-06-14T10:20:09+0300. Current time: 2016-06-14T10:19:37+0300´
jwtHeaderAndClaim 是仅删除签名部分后的 JWT 字符串(即:“xxxxxx.yyyyyyyy.”)。如果我把 jwtString (xxxxxxx.yyyyyyyy.ccccccc) 而不是 jwtHeaderAndClaim 会发生以下错误:
Exception: io.jsonwebtoken.UnsupportedJwtException: Signed JWSs are not supported
如果我把setSigningKey如stormpath example所示:
Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(apiKey.getSecret())).parseClaimsJwt(jwtString).getBody();.
上面的代码不能工作有两个原因: 1.我没有图书馆 导入 javax.xml.bind.DatatypeConverter; 2. 不知道怎么拿到钥匙。
但是知道我不需要密钥,因为这次我尝试登录并收集用户信息(如名字、姓氏、电话等)和签名(令牌),以便下次发送要存储到服务器端的数据我有访问后端的令牌。
谁能帮帮我?
【问题讨论】:
【参考方案1】:你有很多问题。我试着回答其中一些
io.jsonwebtoken.PrematureJwtException: 之前不能接受 JWT 2016-06-14T10:20:09+0300。当前时间:2016-06-14T10:19:37+0300´
您正在 JWT 中使用 nbf(不是之前)属性。不要使用它(它是可选的)或设置一个有效范围,因为设备的时钟不会同步
来自 RFC 7519
“nbf”(不是之前)声明标识 JWT 之前的时间 不得接受处理。 “nbf”声明的处理要求当前日期/时间必须晚于或等于“nbf”声明中列出的非早于日期/时间。 实施者可以提供一些小的余地,通常不超过几分钟,以解决时钟偏差。它的值必须是一个包含 NumericDate 值的数字。 此声明的使用是可选的。
签名的 JWS
异常:io.jsonwebtoken.UnsupportedJwtException:签名的 JWS 是 不支持
您想在客户端还是在服务器端验证签名密钥? 如果您使用 JWT 进行身份验证替换用户和密码,并且您在每个请求中发送令牌,则可以在服务器端验证签名。
如果您想验证应用程序上的密钥,请不要使用对称密钥,因为如果落入坏人之手,它可能是一个很大的漏洞。 See。您可以使用非对称密钥对。使用私钥在服务器中签署 JWT,并使用公钥在设备上进行验证。
我没有库导入 javax.xml.bind.DatatypeConverter
String base64 = Base64.encodeToString(data, Base64.DEFAULT);
byte[] data = Base64.decode(base64, Base64.DEFAULT);
我不知道如何获得密钥。
您的密钥可能是在服务器端以这种方式生成的
Key key = MacProvider.generateKey(SignatureAlgorithm.HS256);
byte data[] = key.getEncoded();
以您喜欢的方式向客户提供密钥data[]
。使用非对称密钥,您只需提供公钥即可。
KeyPair keyPair = RsaProvider.generateKeyPair();
byte data[] = keyPair.getPublic().getEncoded();
【讨论】:
以上是关于如何在 Android 上从 JWT 收集签名、标头和正文的主要内容,如果未能解决你的问题,请参考以下文章