Java 如何为JWT生成和访问密钥

Java 如何为JWT生成和访问密钥,java,security,authentication,jwt,Java,Security,Authentication,Jwt,我正在开发一个RESTAPI,我决定使用JWT进行身份验证/安全性。有一个服务来处理登录验证,还有一个过滤器来绑定到每个需要身份验证的服务 LoginService.java: @Path("login") public class LoginService { private final static long EXPIRATION_TIME = 60000; @POST @Produces("application/json") @Consumes("application/js

我正在开发一个RESTAPI,我决定使用JWT进行身份验证/安全性。有一个服务来处理登录验证,还有一个过滤器来绑定到每个需要身份验证的服务

LoginService.java:

@Path("login")
public class LoginService {

    private final static long EXPIRATION_TIME = 60000;

@POST
@Produces("application/json")
@Consumes("application/json")
public Response authenticateUser(Credentials c) {
    Users login;
    UsersDAO u = new UsersDAO();
    try {
        login = u.getAuthentication(c);

        String token = generateToken(login.getIdUser(), login.getLogin(), login.getRole());

        // Return the token on the response
        return Response.ok().header(AUTHORIZATION, "Bearer " + token).build();
    } catch (Exception e){
        System.out.println("Exception: " + e.toString());
        return Response.status(Response.Status.UNAUTHORIZED).build();
    }      
}

private String generateToken(int id, String login, int role) {
    long nowMillis = System.currentTimeMillis();
    Date now = new Date(nowMillis);

    //TODO generate key (or retrieve it from file/database?)
    Key key;

    String jwtToken = Jwts.builder()
            .setSubject(login)
            .setIssuer("my_company")
            .setIssuedAt(now)
            .setExpiration(new Date(nowMillis + EXPIRATION_TIME))
            .claim("role", role)
            .signWith(SignatureAlgorithm.HS512, key)
            .compact();
    return jwtToken;
    }
JWTTokenFilter.java:

@Provider
@JWTTokenNeeded
@Priority(Priorities.AUTHENTICATION)
public class JWTTokenFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

    String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);

    String token = authorizationHeader.substring("Bearer".length()).trim();

    try {    
        // TODO generate key (or retrieve it from file/database?)
        Key key;
        Jwts.parser().setSigningKey(key).parseClaimsJws(token);

    } catch (Exception e) {
        requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
    }
    }
}  
我一直在做一些研究,但我仍然不确定如何管理密钥生成/验证。我的疑问是:

  • 如果在进行身份验证时创建密钥,如何将同一密钥传递给筛选器?我见过一些代码示例,其中在使用随机数进行身份验证和验证时都会生成密钥,这对我来说毫无意义,因为生成的密钥不会相同。我错过了什么
  • 另一种选择是将密钥存储在文件系统中,以便身份验证和验证过程都能够访问相同的密钥。这会给实现带来什么负面影响(如果有的话)?有没有好的库或框架来管理文件系统(甚至数据库)中的密钥生成和访问

请注意,我不想将密钥传递给客户机,因此他们必须偶尔进行一次身份验证才能刷新令牌,因为他们无法访问到期日期。主题不适合我的情况,它非常完整,但没有任何示例

如果您在运行时生成对称密钥,您可以使用spring注入或使用静态变量在筛选器和登录类之间共享它

<>但请考虑重新启动服务器会使所有发布的JWT失效。如果这不是所需的行为,则需要将密钥保留在属性文件或数据库中

使用Jjwt,您可以执行以下操作:

//generate a random HMAC
Key key = MacProvider.generateKey(SignatureAlgorithm.HS256);

//Get the key data
byte keyData[]= key.getEncoded();
//Store data in a file...

//Build key
Key key = new SecretKeySpec(keyData, SignatureAlgorithm.HS256.getJcaName());

如果在运行时生成对称密钥,则可以使用spring注入或使用静态变量在筛选器和登录类之间共享该密钥

<>但请考虑重新启动服务器会使所有发布的JWT失效。如果这不是所需的行为,则需要将密钥保留在属性文件或数据库中

使用Jjwt,您可以执行以下操作:

//generate a random HMAC
Key key = MacProvider.generateKey(SignatureAlgorithm.HS256);

//Get the key data
byte keyData[]= key.getEncoded();
//Store data in a file...

//Build key
Key key = new SecretKeySpec(keyData, SignatureAlgorithm.HS256.getJcaName());