Я следовал этому учебнику
Все отлично работает, когда я использую почтальон. Однако, когда я попытался использовать библиотеку залпов для аутентификации из моего приложения для Android, она выдает следующую ошибку. Я подозреваю, как я посылаю полезную нагрузку или заголовки. Как должен выглядеть мой заголовок для выполнения аутентификации?
ActionController :: ParameterMissing (параметр отсутствует или значение пусто: auth):
actionpack (5.2.3) lib/action_controller/metal/strong_parameters.rb:443:in `require'
knock (2.1.1) app/controllers/knock/auth_token_controller.rb:44:in `auth_params'
knock (2.1.1) app/controllers/knock/auth_token_controller.rb:31:in `entity'
knock (2.1.1) app/controllers/knock/auth_token_controller.rb:13:in `authenticate'
activesupport (5.2.3) lib/active_support/callbacks.rb:426:in `block in make_lambda'
activesupport (5.2.3) lib/active_support/callbacks.rb:198:in `block (2 levels) in halting'
actionpack (5.2.3) lib/abstract_controller/callbacks.rb:34:in `block (2 levels) in <module:Callbacks>'
activesupport (5.2.3) lib/active_support/callbacks.rb:199:in `block in halting'
activesupport (5.2.3) lib/active_support/callbacks.rb:513:in `block in invoke_before'
activesupport (5.2.3) lib/active_support/callbacks.rb:513:in `each'
activesupport (5.2.3) lib/active_support/callbacks.rb:513:in `invoke_before'
activesupport (5.2.3) lib/active_support/callbacks.rb:131:in `run_callbacks'
actionpack (5.2.3) lib/abstract_controller/callbacks.rb:41:in `process_action'
actionpack (5.2.3) lib/action_controller/metal/rescue.rb:22:in `process_action'
actionpack (5.2.3) lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
activesupport (5.2.3) lib/active_support/notifications.rb:168:in `block in instrument'
activesupport (5.2.3) lib/active_support/notifications/instrumenter.rb:23:in `instrument'
activesupport (5.2.3) lib/active_support/notifications.rb:168:in `instrument'
actionpack (5.2.3) lib/action_controller/metal/instrumentation.rb:32:in `process_action'
actionpack (5.2.3) lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
activerecord (5.2.3) lib/active_record/railties/controller_runtime.rb:24:in `process_action'
actionpack (5.2.3) lib/abstract_controller/base.rb:134:in `process'
actionview (5.2.3) lib/action_view/rendering.rb:32:in `process'
actionpack (5.2.3) lib/action_controller/metal.rb:191:in `dispatch'
actionpack (5.2.3) lib/action_controller/metal.rb:252:in `dispatch'
actionpack (5.2.3) lib/action_dispatch/routing/route_set.rb:52:in `dispatch'
actionpack (5.2.3) lib/action_dispatch/routing/route_set.rb:34:in `serve'
actionpack (5.2.3) lib/action_dispatch/journey/router.rb:52:in `block in serve'
actionpack (5.2.3) lib/action_dispatch/journey/router.rb:35:in `each'
actionpack (5.2.3) lib/action_dispatch/journey/router.rb:35:in `serve'
actionpack (5.2.3) lib/action_dispatch/routing/route_set.rb:840:in `call'
rack (2.0.7) lib/rack/etag.rb:25:in `call'
rack (2.0.7) lib/rack/conditional_get.rb:38:in `call'
rack (2.0.7) lib/rack/head.rb:12:in `call'
activerecord (5.2.3) lib/active_record/migration.rb:559:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (5.2.3) lib/active_support/callbacks.rb:98:in `run_callbacks'
actionpack (5.2.3) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (5.2.3) lib/rails/rack/logger.rb:38:in `call_app'
railties (5.2.3) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (5.2.3) lib/active_support/tagged_logging.rb:71:in `block in
tagged'
activesupport (5.2.3) lib/active_support/tagged_logging.rb:28:in `tagged'
activesupport (5.2.3) lib/active_support/tagged_logging.rb:71:in `tagged'
railties (5.2.3) lib/rails/rack/logger.rb:26:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/request_id.rb:27:in `call'
rack (2.0.7) lib/rack/runtime.rb:22:in `call'
activesupport (5.2.3)
lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/static.rb:127:in `call'
rack (2.0.7) lib/rack/sendfile.rb:111:in `call'
railties (5.2.3) lib/rails/engine.rb:524:in `call'
puma (3.12.1) lib/puma/configuration.rb:227:in `call'
puma (3.12.1) lib/puma/server.rb:660:in `handle_request'
puma (3.12.1) lib/puma/server.rb:474:in `process_client'
puma (3.12.1) lib/puma/server.rb:334:in `block in run'
puma (3.12.1) lib/puma/thread_pool.rb:135:in `block in spawn_thread'
Мой код Android. Примечание: я использовал method1 и method2 отдельно, и объединил, но та же самая ошибка
public class Main2Activity extends AppCompatActivity {
// Creating EditText.
EditText Email, Password;
// Creating button;
Button LoginButton;
// Creating Volley RequestQueue.
RequestQueue requestQueue;
// Create string variable to hold the EditText Value.
String EmailHolder, PasswordHolder;
// Creating Progress dialog.
ProgressDialog progressDialog;
// Storing server url into String variable.
String HttpUrl = "http://10.0.2.2:3000/user_token";
Boolean CheckEditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
// Assigning ID's to EditText.
Email = findViewById(R.id.editText_Email);
Password = findViewById(R.id.editText_Password);
// Assigning ID's to Button.
LoginButton = findViewById(R.id.button_login);
// Creating Volley newRequestQueue .
requestQueue = Volley.newRequestQueue(Main2Activity.this);
// Assigning Activity this to progress dialog.
progressDialog = new ProgressDialog(Main2Activity.this);
// Adding click listener to button.
LoginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CheckEditTextIsEmptyOrNot();
if (CheckEditText) {
UserLogin();
} else {
Toast.makeText(Main2Activity.this, "Please fill all form fields.", Toast.LENGTH_LONG).show();
}
}
});
}
// Creating user login function.
public void UserLogin() {
// Showing progress dialog at user registration time.
progressDialog.setMessage("Please Wait");
progressDialog.show();
// Creating string request with post method.
StringRequest stringRequest = new StringRequest(Request.Method.POST, HttpUrl,
new Response.Listener<String>() {
@Override
public void onResponse(String ServerResponse) {
Log.d("onResponse", ServerResponse);
// Hiding the progress dialog after all task complete.
progressDialog.dismiss();
// Matching server responce message to our text.
if(ServerResponse.equals("200")) {
// If response matched then show the toast.
Toast.makeText(Main2Activity.this, "Logged In Successfully", Toast.LENGTH_LONG).show();
// Finish the current Login activity.
finish();
// Opening the user profile activity using intent.
Intent intent = new Intent(Main2Activity.this, ProfileActivity.class);
// Sending User Email to another activity using intent.
intent.putExtra("UserEmailTAG", EmailHolder);
startActivity(intent);
}
else {
// Showing Echo Response Message Coming From Server.
Toast.makeText(Main2Activity.this, ServerResponse, Toast.LENGTH_LONG).show();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
// Hiding the progress dialog after all task complete.
progressDialog.dismiss();
// Showing error message if something goes wrong.
Log.i("log error", volleyError.toString());
Toast.makeText(Main2Activity.this, volleyError.toString(), Toast.LENGTH_LONG).show();
}
}) {
//METHOD1
@Override
public Map<String, String> getParams() throws AuthFailureError {
// Creating Map String Params.
Map<String, String> params = new HashMap<String, String>();
//code found on stackexhange
params.put("Content-Type", "application/json");
// Adding All values to headers/Params.
// The firs argument should be same as your MySQL database table columns.
params.put("email", EmailHolder);
params.put("password", PasswordHolder);
return params;
}
//METHOD2
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
String credentials = EmailHolder+":"+PasswordHolder;
String auth = "Basic "+ Base64.encodeToString(credentials.getBytes(),
Base64.NO_WRAP);
headers .put("Authorization", auth);
return headers ;
}
};
// Creating RequestQueue.
RequestQueue requestQueue = Volley.newRequestQueue(Main2Activity.this);
//timeout policy
stringRequest.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(stringRequest);
// Adding the StringRequest object into requestQueue.
//requestQueue.add(stringRequest);
}
public void CheckEditTextIsEmptyOrNot() {
// Getting values from EditText.
EmailHolder = Email.getText().toString().trim();
PasswordHolder = Password.getText().toString().trim();
// Checking whether EditText value is empty or not.
if (TextUtils.isEmpty(EmailHolder) || TextUtils.isEmpty(PasswordHolder)) {
// If any of EditText is empty then set variable value as False.
CheckEditText = false;
} else {
// If any of EditText is filled then set variable value as True.
CheckEditText = true;
}
}
}
мой пользовательский контроллер, отлично работает
class UsersController < ApplicationController
# Use Knock to make sure the current_user is authenticated before completing request.
before_action :authenticate_user, only: [:index, :current, :update]
before_action :authorize_as_admin, only: [:destroy]
before_action :authorize, only: [:update]
# Should work if the current_user is authenticated.
def index
render json: {status: 200, msg: 'Logged-in'}
end
# Method to create a new user using the safe params we setup.
def create
user = User.new(user_params)
if user.save
render json: {status: 200, msg: 'User was created.'}
end
end
# Method to update a specific user. User will need to be authorized.
def update
user = User.find(params[:id])
if user.update(user_params)
render json: { status: 200, msg: 'User details have been updated.' }
end
end
# Method to delete a user, this method is only for admin accounts.
def destroy
user = User.find(params[:id])
if user.destroy
render json: { status: 200, msg: 'User has been deleted.' }
end
end
# Call this method to check if the user is logged-in.
# If the user is logged-in we will return the user's information.
def current
current_user.update!(last_login: Time.now)
render json: current_user
end
private
# Setting up strict parameters for when we add account creation.
def user_params
params.require(:user).permit(:username, :email, :password, :password_confirmation)
end
# Adding a method to check if current_user can update itself.
# This uses our UserModel method.
def authorize
return_unauthorized unless current_user && current_user.can_modify_user?(params[:id])
end
end