Spring boot 如何使用Spring(java)验证facebook授权令牌并注册用户
我正在开发一个应用程序,其前端使用React.js编写,后端RESTAPI使用Spring框架编写。我想在我的网站上添加社交登录,所以经过几天的谷歌搜索和研究,我知道OAuth2是解决方案。我知道前端应该处理从资源服务器(这里是Facebook)获取授权令牌的问题,后端(java)应该验证该令牌并与Facebook连接以获取访问令牌。然后,访问令牌应与用户详细信息(如电子邮件)一起存储在我的数据库中 这是我的要求,一旦用户单击“继续使用Facebook”按钮,我的应用程序应该使用详细信息-电子邮件和姓名(注册功能)在我自己的数据库中创建帐户。之后,每当他们再次单击此按钮时,他们将登录而不是注册。其他网站处理它的方式 到目前为止,我的应用程序中有一个按钮,它给我带来了来自Facebook的授权令牌 有人能给我指路吗Spring boot 如何使用Spring(java)验证facebook授权令牌并注册用户,spring-boot,spring-security-oauth2,spring-oauth2,spring-security-rest,Spring Boot,Spring Security Oauth2,Spring Oauth2,Spring Security Rest,我正在开发一个应用程序,其前端使用React.js编写,后端RESTAPI使用Spring框架编写。我想在我的网站上添加社交登录,所以经过几天的谷歌搜索和研究,我知道OAuth2是解决方案。我知道前端应该处理从资源服务器(这里是Facebook)获取授权令牌的问题,后端(java)应该验证该令牌并与Facebook连接以获取访问令牌。然后,访问令牌应与用户详细信息(如电子邮件)一起存储在我的数据库中 这是我的要求,一旦用户单击“继续使用Facebook”按钮,我的应用程序应该使用详细信息-电子邮
此外,我还应该特别注意一些错误处理。以下是使用Spring Boot作为REST API的一般方法,它由Spring Data JPA和Spring Security支持,可同时用于iOS和
ember.js
。可能有一些库以及其他你不能使用的东西,但我只想概述一下基本流程
authToken
进行加密/login/facebook
。我无法预测你的应用程序的结构。在我的应用程序中,此代码由实现GenericFilterBean
的身份验证过滤器处理。我用令牌传递一个标题X-Auth-Facebook
Authentication Authentication(Authentication Authentication)抛出AuthenticationException
方法中实现了AuthenticationProvider
。此类将需要应用程序的访问令牌accessToken
和用户令牌userAccessToken
:EntityNotFoundException
,而不是创建用户,然后我的客户端使用该用户弹出一个注册表,该注册表只提供我无法从facebook获得的字段。从客户端提交此消息时,我使用facebook令牌和创建我的用户所需的内容点击我的/signup/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;
}
@Bean
公共OAuth2ProtectedResourceDetails facebook(){
AuthorizationCodeResourceDetails=新的AuthorizationCodeResourceDetails();
详情。setId(“facebook”);
详情。setClientId(“233668646673605”);
详细信息。setClientSecret(“33b17e044ee6a4fa383f46ec6e28ea1d”);
详细信息。setAccessTokenUri(“https://graph.facebook.com/oauth/access_token");
详细信息。setUserAuthorizationUri(“https://www.facebook.com/dialog/oauth");
详细信息:setTokenName(“oauth_令牌”);
details.setAuthenticationScheme(AuthenticationScheme.query);
setClientAuthenticationScheme(AuthenticationScheme.form);
退货详情;
}
@豆子
公共OAuth2RestTemplate facebookRestTemplate(OAuth2ClientContext客户端上下文){
OAuth2RestTemplate=新的OAuth2RestTemplate(facebook(),clientContext);
MappingJackson2HttpMessageConverter=新的MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON,
MediaType.valueOf(“text/javascript”);
template.setMessageConverters(Arrays.Spring有一个Facebook auth项目,该项目使用Spring Security integration@WildDev。我的发现对吗?当我从前端获取授权令牌时,这是正确的方法吗?还是应该在后端执行所有操作?在后端执行所有操作都会在重定向中产生问题,因为这是一个REST api。这与后端配置有关n、 «继续使用Facebook»默认为本机表单提交者按钮。提交目标为Spring Security endpoint,通过绕过前端逻辑的外部重定向到社交网络进行响应。完成身份验证后,用户将重定向回预定义的返回url。从这一点开始,身份验证
对象包含用户数据,如社交ID等。@ WaldDeV考虑此场景-用户点击“继续使用脸谱网”按钮,按钮与后端API端点<代码> / AUTH/脸谱网> /代码>。Spring Security与脸谱网连接,然后1。如果用户未登录,则脸谱网重定向到登录页面2。这是第一次,用户需要授予对我的应用程序的访问权限,这也需要重定向到fb URL。我的困惑是,REST API如何处理此重定向。例如,在浏览器上(前端)这很简单。我不确定/auth/facebook
端点是否支持REST
体系结构所需的异步请求。文档中最常见的一种是使用同步请求和以下浏览器重定向。没有要求
@Entity
class User{
...
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
FacebookAccount facebookAccount
}
{
status: 'connected',
authResponse: {
accessToken: '...',
expiresIn:'...',
reauthorize_required_in:'...'
signedRequest:'...',
userID:'...'
}
}
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
@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";
}