Bu Raylar API kimlik (Vasiyetle kullanarak) güvenli JSON mi?
Benim Raylar app kimlik doğrulama için Hazırlamak kullanır. Kardeş iOS uygulaması, kullanıcıların iOS uygulaması web uygulaması için kullandığınız aynı kimlik bilgilerini kullanarak giriş yapabilirsiniz. Kimlik doğrulama için API bir tür istiyorum.
Çok benzer sorular burada işaret etmek this tutorial ama sanırım güncel olarak token_authenticatable
modül vardır beri çıkarılması Hazırlamak ve bazı çizgiler atmak hata. (3.2.2. Vasiyet) kullanıyorum Yaptım çalıştı rulo benim kendi dayandığı öğretici (this one), ama ben değilim 100% emin - hissediyorum gibi olabilir bir şey var yanlış veya cevapsız.
Öncelikle, this gist, tavsiyelerini dinlemek ekledim authentication_token
metin users
masam, ve user.rb
aşağıdaki nitelik:
before_save :ensure_authentication_token
def ensure_authentication_token
if authentication_token.blank?
self.authentication_token = generate_authentication_token
end
end
private
def generate_authentication_token
loop do
token = Devise.friendly_token
break token unless User.find_by(authentication_token: token)
end
end
Aşağıdaki denetleyicileri var:
api_controller.rb
class ApiController < ApplicationController
respond_to :json
skip_before_filter :authenticate_user!
protected
def user_params
params[:user].permit(:email, :password, :password_confirmation)
end
end
(Benim not application_controller
satır before_filter :authenticate_user!
.)
/sessions_controller apı.rb
class Api::SessionsController < Devise::RegistrationsController
prepend_before_filter :require_no_authentication, :only => [:create ]
before_filter :ensure_params_exist
respond_to :json
skip_before_filter :verify_authenticity_token
def create
build_resource
resource = User.find_for_database_authentication(
email: params[:user][:email]
)
return invalid_login_attempt unless resource
if resource.valid_password?(params[:user][:password])
sign_in("user", resource)
render json: {
success: true,
auth_token: resource.authentication_token,
email: resource.email
}
return
end
invalid_login_attempt
end
def destroy
sign_out(resource_name)
end
protected
def ensure_params_exist
return unless params[:user].blank?
render json: {
success: false,
message: "missing user parameter"
}, status: 422
end
def invalid_login_attempt
warden.custom_failure!
render json: {
success: false,
message: "Error with your login or password"
}, status: 401
end
end
/registrations_controller apı.rb
class Api::RegistrationsController < ApiController
skip_before_filter :verify_authenticity_token
def create
user = User.new(user_params)
if user.save
render(
json: Jbuilder.encode do |j|
j.success true
j.email user.email
j.auth_token user.authentication_token
end,
status: 201
)
return
else
warden.custom_failure!
render json: user.errors, status: 422
end
end
end
Ve/config yolları.rb:
namespace :api, defaults: { format: "json" } do
devise_for :users
end
Derinliğimi ben ve gelecekteki ben geriye dönüp baktığımda, yalakalık (genellikle yoktur) burada bir şey var eminim. Bazı şüpheli parçalar:
Önceliklegöreceksiniz, dikkat edin Api::SessionsController
miras Devise::RegistrationsController
oysa Api::RegistrationsController
miras ApiController
(bir de diğer denetleyicileri gibi Api::EventsController < ApiController
hangi anlaşma ile daha standart KALAN şeyler için benim diğer modeller ve pek temas ile Sağlanır.) Bu çok çirkin bir düzenlemedir, ama ihtiyacım olan yöntemleri erişim Api::RegistrationsController
girmenin başka bir yolunu bulamadım. Öğretici ben yukarıda bağlantılı include Devise::Controllers::InternalHelpers
ama bu modül Hazırlamak daha yeni sürümlerinde kaldırılmış gibi görünüyor çizgi vardır.
İkincisiÇizgi ile koruma skip_before_filter :verify_authentication_token
CSRF devre dışı bıraktım. Ben benim kuşkularım olsun bu çok iyi bir fikir olduğunu - görüyorum ki bir sürü conflicting hard to understand nasihat olsun JSON API savunmasız CSRF saldırıları - ama ekleme satırı tek yolu bulabilirim lanet şey.
ÜçüncüsüBir kullanıcı imzaladı sonra kimlik doğrulaması nasıl çalıştığını anlamak emin olmak istiyorum. Geçerli kullanıcının arkadaş listesini döndüren 28* *bir API çağrısı var. Anladığım kadarıyla, iOS app kullanıcı authentication_token
almak için veritabanından olurdu hiç değişmiyor her kullanıcı için sabit bir değer olan (??), sonra her istekle birlikte bir parametre olarak göndermek, GET /api/friends?authentication_token=abcdefgh1234
örneğin, Api::FriendsController
User.find_by(authentication_token: params[:authentication_token])
gibi bir şey örnein almak için yapabilir. Gerçekten bu kadar basit mi, ya da ben bir şey eksik?
Bu dev sorunun sonuna kadar okumayı başardım olan herkes için, zaman ayırdığınız için teşekkürler! Özetlemek gerekirse:
- Bu giriş sistemi güvenli mi?Ya gözden kaçan ya da yanlış yaptığım bir şey var CSRF saldırılarına gelince, örneğin?
- Kullanıcılar doğru imzalandığında istekleri kimlik doğrulaması için nasıl benim anlayış?("Üçüncüsü..." yukarıda.)
- Bu kod temizlenebilir ya da iyi yapılmış bir yolu var mı?Özellikle bir denetleyici olması çirkin tasarım
ApiController
33 *ve başkalarından devralmak.
Teşekkürler!
CEVAP
CSRF devre dışı bırakmak istemezsin, insanlar nedense JSON API için geçerli değil sanırım öyle okudum, ama bu bir yanlış anlaşılma. Bu etkin tutmak için, bir kaç değişiklik yapmak istiyorum:
orada sunucu tarafı oturumları denetleyicisi için bir after_filter ekleyin:
after_filter :set_csrf_header, only: [:new, :create] protected def set_csrf_header response.headers['X-CSRF-Token'] = form_authenticity_token end
Bu bir simge oluşturur, seans koymak ve seçilen eylemler için yanıt Başlığı kopyalayın.
istemci tarafında (iOS) iki şeyin yerinde olduğundan emin olun.
müvekkiliniz bu başlık için tüm sunucu yanıt tarama ve birlikte geçirilen zaman korumak gerekiyor.
... get ahold of response object // response may be a NSURLResponse object, so convert: NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; // grab token if present, make sure you have a config object to store it in NSString *token = [[httpResponse allHeaderFields] objectForKey:@"X-CSRF-Token"]; if (token) [yourConfig setCsrfToken:token];
son olarak, istemci tüm bu simge eklemek gerekiyor 'non' istekleri gönderir:
... get ahold of your request object if (yourConfig.csrfToken && ![request.httpMethod isEqualToString:@"GET"]) [request setValue:yourConfig.csrfToken forHTTPHeaderField:@"X-CSRF-Token"];
Bulmacanın son parçası içinde bulmak için günlük/csrf belirteçleri iki sonraki seans kullanıldığını anlamak için. Giriş akışı şu şekilde görünecektir:
GET /users/sign_in ->
// new action is called, initial token is set
// now send login form on callback:
POST /users/sign_in <username, password> ->
// create action called, token is reset
// when login is successful, session and token are replaced
// and you can send authenticated requests
Raylar, nasıl bir render görünümü kull...
Raylar 3 Vasiyetle kullanarak Nasıl bi...
Uzanan SessionsController JSON kullana...
Ne kadar çok baskı JavaScript kullanar...
Güvenli bir nesne içine bir JSON dize ...