Как проверить токен авторизации facebook и зарегистрировать пользователя с помощью Spring(Java)
Я занимаюсь разработкой приложения, внешний интерфейс которого написан с использованием React.js, а внутренний REST API написан с использованием среды Spring. Я хотел добавить социальные логины на свой сайт, поэтому после нескольких дней поисков и поисков я понял, что OAuth2 - это решение. Я узнал, что внешний интерфейс должен обрабатывать получение токена авторизации с сервера ресурсов (здесь Facebook), а мой бэкэнд (java) должен проверять этот токен и соединяться с Facebook, чтобы получить токен доступа. Затем этот токен доступа должен быть сохранен в моей базе данных вместе с данными пользователя (например, электронной почтой).
Вот мое требование, когда пользователь нажимает кнопку "Продолжить с Facebook", мое приложение должно создать там учетную запись в моей собственной базе данных, используя данные - адрес электронной почты и имя (функция регистрации). И позже, когда они снова нажмут на эту кнопку, они войдут в систему, а не зарегистрируются. То, как другие сайты справляются с этим.
На данный момент в моем приложении работает кнопка, которая приносит мне токен авторизации от Facebook.
Может кто-нибудь, пожалуйста, наставьте мне путь, по которому я должен идти.
Кроме того, любое особое внимание к обработке ошибок я должен следовать.
0 ответов
Вот общий подход с использованием Spring Boot в качестве REST API, поддерживаемого Spring Data JPA и Spring Security, который работает для iOS и ember.js
все вместе. Вероятно, есть библиотеки и что-то еще, что вы можете использовать, но я просто собираюсь обрисовать основной поток.
- Вашему объекту пользователя необходимо сопоставление один к одному с учетной записью facebook. Лучшая практика предполагает шифрование
authToken
перед сохранением в БД
@Entity
class FacebookAccount {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
Long id
String facebookUserId
String authToken
@OneToOne
@JoinColumn(name="user_id")
User user
}
@Entity
class User{
...
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
FacebookAccount facebookAccount
}
- Используйте Facebook Javascript SDK, чтобы получить токен доступа пользователя и идентификатор пользователя Facebook. Вы получите ответ от facebook в своем приложении для реагирования, который в успешном случае выглядит следующим образом:
{
status: 'connected',
authResponse: {
accessToken: '...',
expiresIn:'...',
reauthorize_required_in:'...'
signedRequest:'...',
userID:'...'
}
}
Ударьте некоторую конечную точку входа с информацией, полученной на шаге 2, например
/login/facebook
. Я не могу предсказать, как устроено ваше приложение. В моем приложении этот код обрабатывается моим фильтром аутентификации, который реализуетGenericFilterBean
. Я передаю заголовокX-Auth-Facebook
с токеном.Проверить токен. Я делаю это в классе, который реализует
AuthenticationProvider
в пределахAuthentication authenticate(Authentication authentication) throws AuthenticationException
метод. Этому классу потребуется токен доступа вашего приложения.accessToken
и токен пользователяuserAccessToken
:
URIBuilder builder = URIBuilder.fromUri(String.format("%s/debug_token", "https://graph.facebook.com"))
builder.queryParam("access_token", accessToken)
builder.queryParam("input_token", userAccessToken)
URI uri = builder.build()
RestTemplate restTemplate = new RestTemplate()
JsonNode resp = null
try {
resp = restTemplate.getForObject(uri, JsonNode.class)
} catch (HttpClientErrorException e) {
throw new AuthenticationServiceException("Error requesting facebook debug_token", e)
}
Boolean isValid = resp.path("data").findValue("is_valid").asBoolean()
if (!isValid)
throw new BadCredentialsException("Token not valid")
String fbookUserId = resp.path("data").findValue("user_id").textValue()
if (!fbookUserId)
throw new AuthenticationServiceException("Unable to read user_id from facebook debug_token response")
// spring data repository that finds the FacebookAccount by facebook user id
FacebookAccount fbookAcct = facebookAccountRepository.findByFacebookUserId(fbookUserId)
if(!fbookAcct){
// create your user here
// save the facebook account as well
} else{
// update the existing users token
fbookAcct.authToken = userAccessToken
facebookAccountRepository.save(fbookAcct)
}
// finish the necessary steps in creating a valid Authentication
Я лично затем создаю токен, который мой клиент использует при доступе к моему API (вместо того, чтобы они продолжали передавать токен facebook со всеми запросами).
Мне также нужно больше информации, предоставленной пользователем, для создания пользователя (выбранное имя пользователя, согласие с условиями и т. Д.). Итак, моя фактическая реализация вызываетEntityNotFoundException
вместо создания пользователя, которого мои клиенты затем используют для отображения формы регистрации, которая предоставляет только поля, которые я не могу получить из facebook. После отправки этого от клиента я нажал/signup/facebook
конечная точка с токеном facebook и что нужно для создания моего пользователя. Я получаю профиль из facebook и создаю пользователя (автоматически регистрируя его в процессе).
Изменить: если вы хотите использовать Spring 0Auth, вы можете следовать примеру для создания шаблона Spring 2 Oauth Rest
@Bean
public OAuth2ProtectedResourceDetails facebook() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setId("facebook");
details.setClientId("233668646673605");
details.setClientSecret("33b17e044ee6a4fa383f46ec6e28ea1d");
details.setAccessTokenUri("https://graph.facebook.com/oauth/access_token");
details.setUserAuthorizationUri("https://www.facebook.com/dialog/oauth");
details.setTokenName("oauth_token");
details.setAuthenticationScheme(AuthenticationScheme.query);
details.setClientAuthenticationScheme(AuthenticationScheme.form);
return details;
}
@Bean
public OAuth2RestTemplate facebookRestTemplate(OAuth2ClientContext clientContext) {
OAuth2RestTemplate template = new OAuth2RestTemplate(facebook(), clientContext);
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON,
MediaType.valueOf("text/javascript")));
template.setMessageConverters(Arrays.<HttpMessageConverter<?>> asList(converter));
return template;
}
а затем в использовании:
public String photos(Model model) throws Exception {
ObjectNode result = facebookRestTemplate
.getForObject("https://graph.facebook.com/me/friends", ObjectNode.class);
ArrayNode data = (ArrayNode) result.get("data");
ArrayList<String> friends = new ArrayList<String>();
for (JsonNode dataNode : data) {
friends.add(dataNode.get("name").asText());
}
model.addAttribute("friends", friends);
return "facebook";
}
Вышеуказанный запрос для друзей я взял из проекта. нетрудно адаптировать приведенный выше код с помощьюdebug_token
использовать шаблон отдыха Spring OAuth. Надеюсь это поможет:)