身份验证:RoR中的JWT和android

时间:2016-09-03 09:48:58

标签: android ruby-on-rails retrofit jwt

Ruby 2.2.4 Rails 5.0.0.1 改造:1.9.0' 奥托:1.3.8'

Hello People,

我只是编程的初学者,我的任务是使用Android Studio创建一个Android应用程序,您可以在其中以用户身份登录和注销。因此 我使用Json Web Token(JWT)在RoR 5 API中编写了基于令牌的身份验证。本教程帮助我:http://tutorials.pluralsight.com/ruby-ruby-on-rails/token-based-authentication-with-ruby-on-rails-5-api)。在curl中放入正确的凭据后,我终于收到了令牌:{"auth_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE0NjA2NTgxODZ9.xsSwcPC22IR71OBv6bU_OGCSyfE89DvEzWfDU0iybMA"}

现在这个工作正常后我尝试在android studio中实现login-function,它应该与我的RoR服务器交互。 我严格遵循了一个教程(https://www.sitepoint.com/retrofit-a-simple-http-client-for-android-and-java/),该教程使用Retrofit进行身份验证。但是我想为我的RoR服务器实现这个。不过我尝试了这个代码。我很高兴,程序可以在rails服务器上与我的ruby进行通信。如果我使用正确的凭据登录Android应用程序,我会在控制台上看到它将被接受。

但是我不知道如何在android上收到消息,登录成功加上一条带有用户名的欢迎消息。正如我所说的,我在RoR中使用了JWT,它给了一个长令牌。改装是否有可能解释此令牌?或者我是否需要为Android安装JSON Web Token?以下是ruby on rails中代码的一部分:

应用/命令/ authenticate_user.rb

class AuthenticateUser
  prepend SimpleCommand

  def initialize(email, password)
    @email = email
    @password = password
  end

  def call
JsonWebToken.encode(user_id: user.id) if user
  end

  private

  attr_accessor :email, :password

  def user
    user = User.find_by_email(email)
    return user if user && user.authenticate(password)

    errors.add :user_authentication, 'invalid credentials'
    nil
  end
end

LIB / json_web_token.rb

class JsonWebToken
  class << self
    def encode(payload, exp = 24.hours.from_now)
      payload[:exp] = exp.to_i
      JWT.encode(payload, Rails.application.secrets.secret_key_base)
    end

    def decode(token)
      body = JWT.decode(token, Rails.application.secrets.secret_key_base)[0]
      HashWithIndifferentAccess.new body
    rescue
      nil
    end
  end
end

这是我的Android应用程序的一部分,该代码来自我所遵循的教程:

public class Communicator {
    private static  final String TAG = "Communicator";
    private static final String SERVER_URL = "http://127.0.0.1/retrofit";

    public void loginPost(String username, String password){
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(SERVER_URL)
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build();
        Interface communicatorInterface = restAdapter.create(Interface.class);
        Callback<ServerResponse> callback = new Callback<ServerResponse>() {
            @Override
            public void success(ServerResponse serverResponse, Response response2) {
                if(serverResponse.getResponseCode() == 0){
                    BusProvider.getInstance().post(produceServerEvent(serverResponse));
                }else{
                    BusProvider.getInstance().post(produceErrorEvent(serverResponse.getResponseCode(), serverResponse.getMessage()));
                }

            }

            @Override
            public void failure(RetrofitError error) {
                if(error != null ){
                    Log.e(TAG, error.getMessage());
                    error.printStackTrace();
                }
                BusProvider.getInstance().post(produceErrorEvent(-200,error.getMessage()));
            }
        };
        communicatorInterface.postData("login", username, password, callback);
    }

    public void loginGet(String username, String password){
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(SERVER_URL)
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build();
        Interface communicatorInterface = restAdapter.create(Interface.class);
        Callback<ServerResponse> callback = new Callback<ServerResponse>() {
            @Override
            public void success(ServerResponse serverResponse, Response response2) {
                if(serverResponse.getResponseCode() == 0){
                    BusProvider.getInstance().post(produceServerEvent(serverResponse));
                }else{
                    BusProvider.getInstance().post(produceErrorEvent(serverResponse.getResponseCode(), serverResponse.getMessage()));
                }
            }

            @Override
            public void failure(RetrofitError error) {
                if(error != null ){
                    Log.e(TAG, error.getMessage());
                    error.printStackTrace();
                }
                BusProvider.getInstance().post(produceErrorEvent(-200,error.getMessage()));
            }
        };
        communicatorInterface.getData("login", username, password, callback);
    }
}

这是android教程中的Php脚本。也许我需要把它转移到红宝石

<?php

    //Post Method here
    if(isset($_POST['method']) == 'login'){
        $username = $_POST['username'];
        $password = $_POST['password'];

        if($username == "admin" && $password == "admin"){
            $response = array('returned_username' => "-admin-",
                              'returned_password' => "-admin-",
                              'message' => "Your credentials are so weak [USING_POST]!",
                              'response_code' => "1");
               echo json_encode($response);

        }else{
            $response = array('response_code' => "-1",
                              'message' => "invalid username or password");
               echo json_encode($response);
        }
    }

php中的json编码包括一个数组(用户名,密码,消息,响应代码)。如何在轨道上的ruby上包含与JWT相同的阵列?任何的想法?我如何在Android上收到消息,登录成功

2 个答案:

答案 0 :(得分:0)

在第JsonWebToken.encode(user_id: user.id) if user行中,您传递了一个包含密钥user_id的哈希值。您可以扩展此行以包含其他属性,有点像 JsonWebToken.encode(user_id: user.id, name: user.name) if user

然后,您需要在Android应用程序中包含一个JWT库并解码服务器响应(从Retrofit获取),您将能够访问您编码的属性。

答案 1 :(得分:0)

有一种方法可以检索令牌值,首先将这些行添加到ServerResponse.java文件中:

@SerializedName("token")
private String token;

String token

this.token = token;

public String getToken() { return token; }

public void setToken(String token) {
    this.token = token;
}

根据已有的内容然后转到主活动并将令牌存储在变量中,如下所示:

String auth_token = serverEvent.getServerResponse().getToken()

接下来,您可以将其设为private final并在项目中使用它。

希望它有所帮助!