从使用JWT令牌的Retrofit到Rest服务器

时间:2017-09-29 23:01:48

标签: rest authorization retrofit token jwt

我的服务器是基于Flask的,我的客户端是android studio,我正在使用改造进行通信。

问题是登录后我无法正确地将jwt令牌从android传递到服务器。

随着邮递员的运作良好: {{url}} / auth - 我以用户身份登录,并获取JWT令牌。 后来我添加了“授权”标题,其值为“JWT {{jwt_token}}”和 {{url}} / users / john - 我要求提供用户信息,这些信息可以毫无问题地收到。

android studio的端点:

public interface RunnerUserEndPoints {
//    @Headers("Authorization")
    @GET("/users/{user}")
    Call<RunnerUser> getUser(@Header("Authorization") String authHeader, @Path("user") String user);

调用本身(发送前access_token是正确的!):

final RunnerUserEndPoints apiService = APIClient.getClient().create(RunnerUserEndPoints.class);
Log.i("ACCESS","Going to send get request with access token: " + access_token);
Call<RunnerUser> call = apiService.getUser("JWT" + access_token, username);
Log.i("DEBUG","Got call at loadData");
call.enqueue(new Callback<RunnerUser>() {
    @Override
    public void onResponse(Call<RunnerUser> call, Response<RunnerUser> response) { ....

来自服务器的响应错误日志:

File "C:\Users\Yonatan Bitton\RestfulEnv\lib\site-packages\flask_restful\__init__.py", line 595, in dispatch_request
    resp = meth(*args, **kwargs)
  File "C:\Users\Yonatan Bitton\RestfulEnv\lib\site-packages\flask_jwt\__init__.py", line 176, in decorator
    _jwt_required(realm or current_app.config['JWT_DEFAULT_REALM'])
  File "C:\Users\Yonatan Bitton\RestfulEnv\lib\site-packages\flask_jwt\__init__.py", line 151, in _jwt_required
    token = _jwt.request_callback()
  File "C:\Users\Yonatan Bitton\RestfulEnv\lib\site-packages\flask_jwt\__init__.py", line 104, in _default_request_handler
    raise JWTError('Invalid JWT header', 'Unsupported authorization type')
flask_jwt.JWTError: Invalid JWT header. Unsupported authorization type
10.0.0.6 - - [30/Sep/2017 01:46:11] "GET /users/john HTTP/1.1" 500 -

我的api-client

public class APIClient {
    public static final String BASE_URL = "http://10.0.0.2:8000";
    private static Retrofit retrofit = null;


    public static Retrofit getClient(){
        if (retrofit==null){
            retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

        }
        Log.i("DEBUG APIClient","CREATED CLIENT");
        return retrofit;
    }
}

其实我真的被困了。试图按照改造网站上的所有教程进行操作,但没有成功。 我确信有一个简单的解决方案,我只需要添加“授权”标题,其值为“JWT”+ access_token,就像它在邮递员中工作一样,就是这样!感谢。

编辑: 问题是在我的客户端构建access_token。 我做了:                     JsonElement ans = response.body()。get(“access_token”);                     access_token =“JWT”+ ans.toString(); 我应该做的:                     JsonElement ans = response.body()。get(“access_token”);                     access_token =“JWT”+ ans.getAsString();

所以在发送“JWT”之前......“”(Double“”) 现在它发送“JWT ey ......”

1 个答案:

答案 0 :(得分:0)

让我们开始看看我们对这个问题的了解。

  • 我们知道请求已发送
  • 我们知道服务器处理请求
  • 由于错误,我们知道JWT无效:

    JWTError(&#39;无效的JWT标题&#39;,&#39;不支持的授权类型&#39;)

如果我们在flask_jwt source code中查找该错误,我们可以看到这是我们提出错误的地方:

def _default_request_handler():
    auth_header_value = request.headers.get('Authorization', None)
    auth_header_prefix = current_app.config['JWT_AUTH_HEADER_PREFIX']

    if not auth_header_value:
        return

    parts = auth_header_value.split()

    if parts[0].lower() != auth_header_prefix.lower():
        raise JWTError('Invalid JWT header', 'Unsupported authorization type')
    elif len(parts) == 1:
        raise JWTError('Invalid JWT header', 'Token missing')
    elif len(parts) > 2:
        raise JWTError('Invalid JWT header', 'Token contains spaces')

    return parts[1]

基本上flask_jwt获取Authorization标头值并尝试将其拆分为两个。函数split可以用分隔符分割字符串,但是如果你在没有分隔符it will use whitespace的情况下调用它。

这告诉我们flask_jwt期望一个字符串包含由空格分隔的2个部分,例如空格,并且第一部分必须与我们使用的前缀匹配(在本例中为JWT)。

如果我们返回并查看您的客户端代码,我们可以看到,当您构建要放入Authorization标头的值时,您不会在JWT和实际值之间添加空格令牌:

apiService.getUser("JWT" + access_token, username);

这是你应该做的:

apiService.getUser("JWT " + access_token, username);

注意JWT之后的空格?