2016-11-28 66 views
0

我在Android上使用基本jwt验证连接到REST服务时遇到问题。我为我的Android代码使用OkHttp 3和Retrofit 2。服务器是在AWS elasticbeanstalk上运行的node.js Hapi服务器,具有默认的nginx代理配置。所有后端正在为每次调用检查身份验证令牌。具有基本令牌验证的OkHttp适用于GET但不适用于DELETE

问题:我的GET和DELETE都需要令牌的“授权”标头。当我用令牌调用GET时,它可以工作。当我用令牌删除时,我得到了一个403 ACCESS DENIED,但只有当android设备连接到蜂窝网络并具有ipv6地址时。当它连接到我的家庭无线网络时,它正常工作。

对于一些更多的信息,直接连接到端口8080上的NodeJS服务器也使一切工作正常。我想在图片中保留nginx,以防我想在同一个盒子上运行多个节点服务器副本。另外,我对此很新,很高兴考虑任何替代方案。

下面是Android代码:

Gson gson = new GsonBuilder().create(); 

    OkHttpClient okClient = new OkHttpClient.Builder() 
      .readTimeout(40, TimeUnit.SECONDS) 
      .writeTimeout(40, TimeUnit.SECONDS) 
      .addInterceptor(
        new Interceptor() { 
         @Override 
         public okhttp3.Response intercept(Chain chain) throws IOException { 
          Request original = chain.request(); 

          //auth token for every request 
          Request.Builder requestBuilder = original.newBuilder() 
            .addHeader("Authorization", authToken); 
          Request request = requestBuilder.build(); 

          // it correctly prints out header with the token for both GET and DELETE 
          Log.d("ApiManager", "HEADERS: " + request.headers().toString()); 

          okhttp3.Response response = chain.proceed(request); 
          return response; 
         } 
        }).build(); 

    Retrofit retrofit = new Retrofit.Builder() 
      .client(okClient) 
      .baseUrl(MyApi.baseUrl) 
      .addConverterFactory(GsonConverterFactory.create(gson)) 
      .build(); 

    myApi = retrofit.create(MyApi.class); 

我的Nginx的设置:

upstream nodejs { 
    server 127.0.0.1:8081; 
    keepalive 256; 
} 

server { 
    listen 8080; 

    if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") { 
     set $year $1; 
     set $month $2; 
     set $day $3; 
     set $hour $4; 
    } 
    access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd; 
    access_log /var/log/nginx/access.log main; 

    location/{ 
     proxy_pass http://nodejs; 
     proxy_set_header Connection ""; 
     proxy_http_version 1.1; 
     proxy_set_header  Host   $host; 
     proxy_set_header  X-Real-IP  $remote_addr; 
     proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for; 
    } 

    gzip on; 
    gzip_comp_level 4; 
    gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; 

} 

UPDATE:看来,如果我在我的Android设备连接到Wi-Fi网络的工作,但如果我连接到我的移动网络则无法使用。我卡住了。 来自服务器上的nginx访问日志。它不记录403错误:

  1. Android设备连接到蜂窝网络:IP: “2001:56A:6ffc:d07e:0:47:2e8a:4101,142.59.70.25” GET和POST请求工作,但DELETE不。
  2. Android设备连接到wifi:IP:“96.51.151.36”,GET,POST和DELETE工作。
+0

不知道您当前的代码有什么问题,但我通常在我的Retrofit界面中使用'@ Headers'注释来定义标题。请参阅[他们的文档](https://futurestud.io/tutorials/retrofit-add-custom-request-header)了解更多信息。 – Joris

+0

您的蜂窝数据网络可能会阻止PUT和DELETE请求。如果是这种情况,使用https将隐藏来自防火墙的标题,并且您的请求将通过。 –

+0

相关[RESTful PUT和DELETE和防火墙](http://stackoverflow.com/questions/1828790/restful-put-and-delete-and-firewalls) –

回答

1

如果POST工程和DELETE不然后尝试使用HTTP方法重载与任X-HTTP-Method-Override头或_method查询参数,看看是否可行的方式。

如果它开始工作,然后你就会知道它是在HTTP水平(比如一些代理问题)的问题。如果没有,那么你会知道这是你的路由处理程序的问题。

请参阅Common non-standard request fields的维基百科。从长远来看,你是否想要使用它是另一个问题,但它可以让你快速缩小问题的范围。

你没有张贴任何后端代码,你甚至没有说什么框架被用在后端因此,可以提供关于如何做到这一点没有明确的答案。如果您使用的是Express,那么您可以使用method-override中间件。

另外,在你发布的关于同一问题的其他问题之一中,你展示了你的nginx配置,看起来你所做的基本上是代理8080到8081之间的流量。尝试直接连接到8081,以排除它是您自己的代理导致问题的可能性。

(顺便说一下,它会如果你发布的所有相关信息的一个问题,而不是3个或4大致相同的问题类似的问题之间散播的更容易。可以编辑问题以在发布后添加更多信息。请参阅:How do edits work以了解更多信息。)

+0

感谢您的回答,我删除了所有重复的问题。 8080到8081代理设置仅是nginx的默认AWS弹性beanstalk配置。我试图直接连接到8080,问题消失。在nginx访问日志中,不再为移动网络上的设备记录ipv6地址(而是使用“ - ”)。 – Vlad

相关问题