使用JWT身份验证进行改造 - 如何通知拦截器当前用户?

时间:2017-10-07 19:20:37

标签: java spring retrofit2 okhttp

我正在使用Retrofit 2.3.0与使用JWT从Spring Boot应用程序进行身份验证的API进行通信。

为了使其有效,我创建了一个Interceptor实现:

private static class JwtAuthenticationInterceptor implements Interceptor {
    private Supplier<String> jwtTokenSupplier;

    private JwtAuthenticationInterceptor(Supplier<String> jwtTokenSupplier) {
        this.jwtTokenSupplier = jwtTokenSupplier;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request original = chain.request();

        Request.Builder builder = original.newBuilder()
                                          .header("Authorization",
                                                  String.format("Bearer %s", jwtTokenSupplier.get()));

        Request request = builder.build();
        return chain.proceed(request);
    }
}

在我的Spring服务中,我让Retrofit在构造函数中创建API接口的实例:

public MySringServiceImpl() {
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(createLoggingInterceptor())
            .addInterceptor(new JwtAuthenticationInterceptor(this::createJwtToken))
            .build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://my.remoteapi.com/api/")
            .addConverterFactory(JacksonConverterFactory.create())
            .client(client)
            .build();

    api = retrofit.create(MyRemoteApi.class);
}

所以在我的服务的实际方法中,我使用这样的东西:

public List<Stuff> getStuffFromApi() {
    try {
        List<Stuff> response = api.getStuff().execute().body();
        if (response != null) {
            return response;
        } else {
            return new ArrayList<>();
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

createJwtToken方法创建JWT令牌(使用Java JWT library

private String createJwtToken() {
    return Jwts.builder()
               .setIssuer("http://my.remoteapi.com/api/")
               .setId("my-test-id")
               .setIssuedAt(new Date())
               .setExpiration(new Date(ZonedDateTime.now().plusSeconds(60).toEpochSecond() * 1000))
               .claim("uid", "123")
               .signWith(SignatureAlgorithm.HS512,
                         "my-very-secret-key"
                                 .getBytes())
               .compact();
}

实际问题:

uid声明需要包含当前用户的ID(而不是像现在这样硬编码)。我很清楚如何在RestController中获取Spring主体并将其传递给服务,但是我如何指示拦截器使用该主体的id来进行正在进行的调用?我应该为每个调用创建一个新的Retrofit实例,还是有更好的方法来处理它?<​​/ p>

0 个答案:

没有答案