微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何通过 OkHttp 和 Retrofit 为 Spring 应用程序提供凭据

如何解决如何通过 OkHttp 和 Retrofit 为 Spring 应用程序提供凭据

我开发了具有 webflux 基本身份验证的 spring 非 Web 服务。 它的工作原理,我能够成功地使用 cURL 到达某些端点,例如:

curl -I --user user:password http://localhost:5051/service/v1/health
or
curl -I http://user:password@localhost:5051/service/v1/health

但现在我试图通过其他使用 OkHttp 和 Retrofit 与我的 spring 服务通信的服务发送帖子。

这个过程比较复杂,在主应用中创建OkHttpClient然后分离,调用Retrofit service client provider。

主要应用:

    httpUrl = url
                .newBuilder()
                .username(Username) // first approach
                .password(Password)
                {..}
                .build();
     ClientProvider
                .getInstance(httpUrl,Username,Password)
                .subscribeOn(Schedulers.io())
                .subscribe(new ProfiledSingleObserver<Event>() {
                    @Override
                    public void profiledOnError(@NotNull Throwable e) {
                        LOG.error("Transport layer error",e);
                        resultFuture.completeExceptionally(e);
                    }

            @Override
                    public void profiledOnSuccess(@NotNull Event event) {
                        resultFuture.complete(Collections.singleton(event));
                    }
                });
public class ClientProvider {
    private static HttpUrl httpUrl = null;
    private static Service instance = null;

    private ClientProvider() {
    }

    public static Service getInstance(final HttpUrl url,String username,String password) {
      
                instance = Client.createService(url,HttpClient.getInstance(username,password));
         
        return instance;
    }
}
  public static OkHttpClient getInstance(String username,String password) {
        if (instance == null) {
            synchronized (lock) {
                instance = new OkHttpClient.Builder()

//                        .authenticator(new Authenticator() { // second approach
//                            @Override
//                            public Request authenticate(@Nullable Route route,@NotNull Response response) throws IOException {
//                                return response
//                                        .request().newBuilder()
//                                        .header("Authorization",Credentials.basic(username,password))
//                                        .build();
//                            }
//                        })
//                        .addInterceptor(new BasicAuthInterceptor(username,password)) // third approach
                        .addInterceptor(createHttpBodyLoggingInterceptor())
                        .addInterceptor(createHttpBasicLoggingInterceptor())
                        .writeTimeout(10,TimeUnit.SECONDS)
                        .readTimeout(10,TimeUnit.SECONDS)
                        .connectTimeout(10,TimeUnit.SECONDS)
                        .dispatcher(createdispatcher())
                        .connectionPool(createConnectionPool())
                        .build();
            }
        }
        return instance;
    }
public class BasicAuthInterceptor implements Interceptor {

    private final String credentials;

    public BasicAuthInterceptor(String user,String password) {
        this.credentials = Credentials.basic(user,password);
    }

    @NotNull
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Request authenticatedRequest = request.newBuilder()
                .header(HttpHeaders.AUTHORIZATION,credentials).build();
        return chain.proceed(authenticatedRequest);
    }
}

以及 Retrofit 服务客户端提供商:

 public static Service createService(final HttpUrl baseUrl,final OkHttpClient okHttpClient) {
        return createRetrofit(baseUrl,okHttpClient).create(Service.class);
    }

    protected static Retrofit createRetrofit(HttpUrl baseUrl,OkHttpClient client) {

        return new Retrofit
                .Builder()
                .baseUrl(baseUrl)
                .client(client)
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .addConverterFactory(JacksonConverterFactory.create())
                .build();
    }

我采用了 3 种不同的方法解决这个问题,正如您在它们旁边的评论中看到的那样。 首先只是通过 url 传递用户名和密码,看起来像:

 http://user:password@localhost:5051/service/v1/health

但即使使用此符号的 curl 有效,身份验证也未通过。

第二种方法是在 OkHttpClient.Builder() 中创建 Authenticator。 结果还是一样。

第三个是在 OkHttpClient 中创建拦截器。 在这方法中,我能够通过存根服务器的单元测试, 这在其他解决方案中是不可能的(状态 404,未找到):

    @BeforeClass
    public static void setUpClass() {
        serviceStubServer = new StubServer();
        whenHttp(serviceStubServer)
                .match(Condition.basicAuth("user","pass"),Condition.post("/service/v1/health"))
                .then(
                        Action.status(HttpStatus.OK_200),);
        serviceStubServer.run();
    }

但我仍然无法通过我的主应用程序将记录发送到我的 Spring 服务(状态 401,未授权)。

我的问题是,通过 OkHttp 和 Retrofit 传递凭据以到达 Spring 非 Web、webflux 基本身份验证安全应用程序中的端点的正确方法是什么?

解决方法

问题似乎在于创建 OkHttpClient 的单例方法。该系统使用两个不同的 Spring 服务运行并记住其中一个凭据,因此他无法正确访问第二个服务。 为了解决这个问题,我创建了第二个 OkHttpClient 类并使用“拦截器”方法来提供授权数据。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?