gpt4 book ai didi

java - JWT 正在发行相同的 token

转载 作者:搜寻专家 更新时间:2023-11-01 02:37:44 26 4
gpt4 key购买 nike

我正在使用 Jersey 制作一个休息 API。我正在使用 java-jwt( https://github.com/auth0/java-jwt ) 进行 token 生成工作。请检查以下代码。

UserJSONInfo - REST 方法类

@Path ("/user_info")
public class UserInfoJSONService
{
@POST
@Path("/authenticateUser")
@Produces(MediaType.APPLICATION_JSON)
public Response authenticateUser(Credentials credentials)
{
UserInfoService service = new UserInfoService();

try{
UserInfo authenticateUser = service.authenticateUser(credentials.getUserName(), credentials.getPassword());
String generateToken = service.generateToken(AuthKey.authorizationSecret);

Authentication auth = new Authentication();
auth.setIdUser(authenticateUser.getIduser());
auth.setToken(generateToken);

return Response.status(Response.Status.OK).entity(auth).build();
//return authenticateUser;
}
catch(IndexOutOfBoundsException e)
{
throw new WebApplicationException(Response.Status.BAD_REQUEST);
} catch (JWTCreationException ex) {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
} catch (UnsupportedEncodingException ex) {
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
}
}

UserInfoService - 服务层

public class UserInfoService {

private static UserInfoDAOInterface userDAOInterface;

public UserInfoService() {
userDAOInterface = new UserInfoDAOImpl();
}

public Session getSession() {
Session session = userDAOInterface.openCurrentSession();
return session;
}

public Transaction getTransaction(Session session) {
Transaction transaction = userDAOInterface.openTransaction(session);
return transaction;
}



public UserInfo authenticateUser(String userName, String password)
{
return authenticate(userName, password);
}

private UserInfo authenticate(String userName, String password) throws IndexOutOfBoundsException
{
Session session = userDAOInterface.openCurrentSession();
Transaction transaction = null;
UserInfo user = new UserInfo();

try {
transaction = userDAOInterface.openTransaction(session);
user = userDAOInterface.authenticate(userName, password, session);
transaction.commit();
// } catch (Exception ex) {
// //ex.printStackTrace();
// System.out.println("OK");
//
} finally {
session.close();
}

return user;
}

public String generateToken(String secret) throws JWTCreationException, UnsupportedEncodingException
{
Token token = new Token();
return token.issueTokenHMAC256(secret);
}

}

AuthKey - 只包含secret

public interface AuthKey {
public static String authorizationSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<servlet>
<servlet-name>ExampleServlet</servlet-name>
<servlet-class>test.ExampleServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>Jersey RESTful Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>rest</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ExampleServlet</servlet-name>
<url-pattern>/ExampleServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Jersey RESTful Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

我将 token 生成类作为另一个 Java 项目进行维护,并将其作为库导入到此处(我使用的是 Netbeans)。下面是代码

package com.xyz.security;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.io.UnsupportedEncodingException;

/**
*
* @author Yohan
*/
public class Token {

/**
* Generate the HMAC256 Token
* @param secret
* Secret to generate the token
* @return
* Token as a String
* @throws UnsupportedEncodingException
* UTF-8 encoding not supported
* @throws JWTVerificationException
* Invalid Signing configuration / Couldn't convert Claims.
*/
public String issueTokenHMAC256(String secret) throws UnsupportedEncodingException, JWTCreationException
{

String token="";
try {
Algorithm algorithm = Algorithm.HMAC256(secret);
token = JWT.create()
.withIssuer("auth0")
.sign(algorithm);


} catch (UnsupportedEncodingException exception) {
//UTF-8 encoding not supported
exception.printStackTrace();
} catch (JWTCreationException exception) {
//Invalid Signing configuration / Couldn't convert Claims.
exception.printStackTrace();
}

return token;
}


/**
* Validate a HMAC256 Token
* @param token
* Token you need to validate
* @param secret
* Secret used to generate the token
* @return
* Returns `true` if token is valid.
* @throws UnsupportedEncodingException
* UTF-8 encoding not supported
* @throws JWTVerificationException
* Invalid Signing configuration / Couldn't convert Claims.
*/
public boolean validateTokenHMAC256(String token, String secret) throws UnsupportedEncodingException, JWTVerificationException
{
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer("auth0")
.build(); //Reusable verifier instance
DecodedJWT jwt = verifier.verify(token);

return true;
}
}

现在的问题是,每次我在用户登录时生成token,我都会得到相同的token。我正在使用 POSTMAN 检查 REST 方法,我打开了 3 个选项卡并为 3 个不同的用户进行了登录尝试。问题是我得到了相同的 token !这是正确的还是错误的?在那种情况下,我该如何解决?

最佳答案

什么是基于 token 的认证方案

在基于 token 的身份验证方案中, token 成为用户的凭据。用户名和密码等硬凭证被交换为必须在每个请求中发送的 token ,然后服务器可以执行身份验证/授权。 token 可以在短时间内有效,可以撤销,可以携带范围详细信息( token 可以请求什么)等。

使用 token ,您必须能够识别以您的 API 为目标的用户。因此,为所有经过身份验证的用户使用一个 token 是没有意义的。

解决您的问题

一旦您使用了 JWT,您就可以使用用户名进行声明。还可以考虑为您的 token 添加到期日期( exp 声明)。您不希望您的 token 永远有效,对吗?

java-jwt ,使用以下内容:

try {

Algorithm algorithm = Algorithm.HMAC256("secret");
Date expirationDate = Date.from(ZonedDateTime.now().plusMinutes(60).toInstant());
String token = JWT.create()
.withExpiresAt(expirationDate)
.withClaim("username", username)
.sign(algorithm);

} catch (UnsupportedEncodingException e){
// UTF-8 encoding not supported
} catch (JWTCreationException e){
// Invalid signing configuration / Couldn't convert claims
}

验证 token 时,您将能够获得 username声明并知道您为谁发行了 token :

try {

Algorithm algorithm = Algorithm.HMAC256("secret");
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);

Claim usernameClaim = jwt.getClaim("username");
String username = usernameClaim.asString();

} catch (UnsupportedEncodingException e){
// UTF-8 encoding not supported
} catch (JWTVerificationException e){
// Invalid signature/claims
}

使用 JWT 处理 token 刷新

接受 有效(未过期)的 token 来提神。客户端有责任在 exp 中指示的到期日期之前刷新 token 。 claim 。

为避免 token 无限期刷新,您可以通过向 token 添加两个声明(声明名称由您决定)来跟踪 token 刷新:

  • refreshLimit : 表示token可以刷新多少次。
  • refreshCount : 表示 token 被刷新了多少次。

因此只有在满足以下条件时才刷新 token :

  • token 未过期 ( exp >= now )。
  • token 已刷新次数小于 token 可刷新次数(refreshCount < refreshLimit)。

刷新 token 时:

  • 更新到期日期 ( exp = now + some-amount-of-time )。
  • 增加 token 刷新的次数 ( refreshCount++ )。

一旦 token 被签名并且签名在服务器端被验证, token 的内容就不能被客户端篡改。

除了跟踪茶点的数量,您还可以有一个表明绝对到期日期的声明。在该日期之前,可以接受任意数量的点心。

另一种方法涉及发布一个单独的长期刷新 token ,该 token 用于发布短期 JWT token 。

最佳方法取决于您的要求。

使用 JWT 处理 token 撤销

如果你想撤销 token ,你必须跟踪它们。您不需要在服务器端存储整个 token ,只存储 token 标识符(必须是唯一的)和一些元数据(如果需要)。对于 token 标识符,您可以使用 UUID .

jti claim 应用于将 token 标识符存储在 token 本身上。验证 token 时,通过检查 jti 的值确保 token 未被撤销针对您在服务器端拥有的 token 标识符提出 claim 。

出于安全考虑,当用户更改密码时,撤销用户的所有 token 。


有关 JAX-RS 中基于 token 的身份验证的更多详细信息,请参阅此 answer .

关于java - JWT 正在发行相同的 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42974472/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com