Я не совсем уверен, что вы подразумеваете под «без гражданства». Вам, очевидно, нужна база данных для хранения данных пользователя (в противном случае вам вообще не нужен бэкэнд). Таким образом, база данных - это ваше состояние. Протокол HTTP по определению не имеет апатридов, поэтому вы не можете быть очень сдержанным с помощью других средств, кроме хранения данных в БД.
Я попрошу токен аутентификации в SPA или в мобильном приложении. Должен ли я преобразовать это в токен доступа на стороне сервера или на стороне клиента?
Если вам не нужно использовать Google/Facebook от имени пользователей (и вашей редакции предполагает, что вы не), вам не нужно конвертировать auth_token в server_token вообще.
Вам просто нужно позвонить в Google/Facebook API (у Ruby есть библиотеки для обоих, так что это в основном одна строка кода) и получить идентификатор пользователя социальной сети и электронную почту пользователя.
Затем вы сохраняете этот ID + адрес электронной почты в своей базе данных и даете вашему внутренний серверный токен (только случайная строка) вашему пользователю. Вы сами генерируете эту строку и передаете ее клиенту.
Если пользователь входит в систему с другого устройства (т.он дает вам auth_token
, с помощью которого вы узнаете, что адрес электронной почты пользователя принадлежит одному из уже зарегистрированных пользователей), вы либо возвращаете существующий внутренний токен, либо генерируете новый, и привязываете его к существующему пользователю (в зависимости от того, что вы определяете по приоритетам - высокая безопасность простота внедрения/обслуживания).
Я хочу, чтобы иметь возможность объединять аутентификации Google и Facebook, каковы лучшие практики для этого?
Facebook гарантирует что если это дает пользователю по электронной почте, то это обеспечивается что, что электронная почта относится к данному пользователю. Google, очевидно, делает то же самое. Поэтому вы просто объединяете их по электронной почте.
Для этого вам не нужны специальные библиотеки, так как это простая операция с вашим кодом на выбранном вами языке.
Я бы организовать все вещи в базе данных следующим образом: таблицы
Пользователи
id
email
авторизаций стол
user_id
email
social_uid # facebook number or google email
social_network # string, 'facebook' or 'google'
device # user agent, e.g. 'android'
ip # last login IP address
token # internal token
Когда пользователь входит в систему, проверки подлинности объект создается. Если у пользователя нет такого сообщения, пользователь будет создан. Если есть пользователь, он привязывается к объекту аутентификации (как через поле user_id
).
Заметка о лексемах
Если вы планируете взаимодействовать с социальной сетью доступа (другими способами, чем просто аутентифицируется пользователь), вы должны обменять auth_token
для server_token
. server_token
- это «постоянный» (ну, вид) токен авторизации для доступа к API-интерфейсам социальной сети, тогда как auth_token
имеет очень ограниченный срок службы (и некоторые вызовы API могут быть ограничены, если вы не получили server_token
).
По-прежнему может исчезнуть server_token
(или пользователь может вспомнить свой доступ для вашего приложения), поэтому вам следует планировать заранее, чтобы обнаружить эту ситуацию и повторно приобрести токен/авторизацию, если это необходимо.
Ключевые моменты при создании Rails приложение
В Rails, для создания таблиц, вам нужно написать migrations:
gem install rails
rails new my_project
cd my_project
rails generate migration create_users
rails generate migration create_authentications
Это создаст структуру папок проекта и два файла миграции, которая вам нужно заполнить:
# db/migrate/xxx_create_users.rb
def change
create_table :users do |t|
t.string :email
end
end
# db/migrate/xxx_create_authentications.rb
def change
create_table :authentications do |t|
t.integer :user_id
t.index :user_id
t.string :social_uid
# etc., all other fields
# ...
end
end
Затем вы создаете "models «для обработки манипуляции связанные с базой данных:
# app/models/user.rb
class User < ActiveRecord::Base
has_many :authentications
end
# app/models/authentication.rb
class Authentication < ActiveRecord::Base
belongs_to :user
before_create :set_token
after_commit :create_user_if_needed
private
def set_token
self.token = SecureRandom.urlsafe_base64(20)
end
def create_user_if_needed
unless self.user.present?
self.user.create(email: self.email)
end
end
end
И писать» controller "для обработки запроса от пользователя с помощью одного метода внутри него:
# app/controllers/login_controller.rb
class LoginController < ActionController
# Login via Facebook method
def facebook
token = params.require(:auth_token)
# we will use Koala gem
profile = Koala::Facebook::API.new(token).get_object('me', fields: 'email')
# user is created automatically by model
authentication = Authentication.where(social_network: 'facebook', social_uid: profile['id'], email: profile['email']).first_or_create
authentication.update(...) # set ip and device
render json: {token: authentication.token}
end
# This one you'll have to write yourself as an exercise :)
def google
end
end
Конечно, вам нужно настроить routes для действия:
# config/routes.rb
post "login/:action", controller: 'login'
и добавить Koala (или то, что вы будете использовать для управления внешнего API, для которых уже существуют хорошие пакеты Ruby) для Gemfile:
# Gemfile
gem 'koala'
Затем в терминале выполните команду:
bundle install
rails server
И ваше приложение и работает. Ну, сначала вам нужно настроить приложения Facebook и Google, получить ключи от разработчика и разрешить localhost
принять auth_tokens
.
В принципе, все.
Спасибо за очень исчерпывающий ответ, это понятно и понятно. Как изменится этот поток, если мне нужно будет взаимодействовать от имени моих пользователей на Facebook? Я также немного не определился, если я должен сделать это взаимодействие непосредственно из SPA/мобильного приложения (в этом случае я предполагаю, что мне нужно получить там токен доступа) или через серверную базу (там я бы предположил, что мне нужно создать маркер доступа на стороне сервера, а мобильный/SPA вообще не должен знать об этом). – abali
Если у вас несколько клиентов (и вы говорите, что у вас есть как минимум два), это хорошая идея для реализации социальных сетевых взаимодействий на сервере - вам нужно будет сделать это один раз (вместо одного времени для каждого клиента). Какие изменения вы должны приобрести (обменять на 'auth_token') и хранить' server_token', а затем использовать его для доступа к API социальной сети. – EugZol
Спасибо, это действительно имеет смысл. Я предполагаю, что в этом случае лучше всего хранить токен доступа только на стороне сервера и продолжать авторизацию между клиентом и сервером на основе самогенерированного внутреннего токена, то есть я должен проверить все запросы на бэкэнд, если они содержат действительный токен или нет, а если нет, отклоняйте запрос и заставляйте клиента повторно аутентифицироваться с помощью FB/Google. – abali