将 Spring Security 与 Facebook 登录集成
Posted
技术标签:
【中文标题】将 Spring Security 与 Facebook 登录集成【英文标题】:Integrate Spring Security with Facebook Login 【发布时间】:2014-06-19 20:18:47 【问题描述】:我在我的项目中使用 Spring MVC 和 Spring Security。这使用我自己的用户数据进行身份验证。但现在我试图与 Facebook 整合。我在 Facebook 上创建了应用程序,这意味着我得到了客户 ID 和客户密码。我还阅读了 SO 中的一些问题和一些文档,但仍然卡住了......
我创建控制器以使用 Facebook 登录:
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/login/")
public class LoginController
String fb_app_id="my_client_id";
String redirect_url="localhost:8888";
String state="public_profile,email,user_friends";
String key="my_client_secret";
@RequestMapping("/facebook")
public String login( ModelMap model)
String url="https://www.facebook.com/dialog/oauth/?"
+ "client_id=" + fb_app_id
+ "&redirect_uri=" + redirect_url
+ "&scope=email,publish_stream,user_about_me,friends_about_me"
+ "&state=" + key
+ "&display=page"
+ "&response_type=code";
return "redirect:"+url;
我认为它有效,因为当我尝试连接时,我可以在下面使用 javascript 显示我的名字:
function testAPI()
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response)
console.log('Good to see you, ' + response.name + '.');
document.getElementById('status').innerhtml = 'Good to see you, ' +
response.name;
);
但我仍然对如何将它与 Spring Security 集成感到困惑。如果有人有任何例子,我将不胜感激......
这是我的 spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http pattern="/common/*" security="none" />
<http auto-config="true">
<intercept-url pattern="/maintenance/*" access="ROLE_USER" />
<intercept-url pattern="/_ah/*" access="ROLE_USER" />
<intercept-url pattern="/predict/*" access="ROLE_USER" />
<form-login login-page='/' default-target-url='/predict/list'
login-processing-url="/login_check" authentication-failure-url="/index?login_error=2"
always-use-default-target="true" />
<logout logout-url="/logout" logout-success-url="/index" />
<!-- <custom-filter ref="socialAuthenticationFilter" before="PRE_AUTH_FILTER" /> -->
<!-- <custom-filter before="FORM_LOGIN_FILTER"
ref="facebookAuthenticationFilter" /> -->
</http>
<authentication-manager>
<authentication-provider ref="gaeAuthenticationProvider" />
<!-- <authentication-provider ref="authenticationProviderFacebook">
</authentication-provider>-->
</authentication-manager>
<beans:bean id="gaeAuthenticationProvider"
class="com.games.predictor.security.AuthenticationProvider" />
</beans:beans>
我有自己的类来使用 JPA 对用户数据进行身份验证...
package com.games.predictor.security;
import java.util.List;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import com.games.predictor.UserDAO;
public class AuthenticationProvider extends AbstractUserDetailsAuthenticationProvider
//private SecurityDao securityDao;
@Override
protected UserDetails retrieveUser(String username,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException
final String password = authentication.getCredentials().toString();
System.out.println(username+"===="+password);
//This line for validating user with database
boolean isValidUser = UserDAO.INSTANCE.isValidUser(username, password);
if (isValidUser)
final List<SimpleGrantedAuthority> authorities = UserDAO.INSTANCE.getAuthoritiesByUser(username);
//User u=new User(username,password,);
return new User(username, password, true, true, true, true, authorities);
else
authentication.setAuthenticated(false);
throw new BadCredentialsException("Username/Password does not match for "
+ authentication.getPrincipal());
@Override
protected void additionalAuthenticationChecks(UserDetails arg0,
UsernamePasswordAuthenticationToken arg1)
throws AuthenticationException
// TODO Auto-generated method stub
我在过去几天做了一些研究,但仍然卡住了。
我的项目堆栈:Java、Spring MVC、Spring Security、Google App Engine、Google Data Store、JPA。 (添加了 Spring Social Core 和 Spring Social Facebook)
【问题讨论】:
你真的不应该自己做任何这些......你检查过吗:projects.spring.io/spring-security-oauth/docs/oauth2.html,这是项目链接:projects.spring.io/spring-security-oauth 如果你想要一个示例实现,请检查这个。github.com/timenkov/facebook_login 【参考方案1】:我认为您不应该手动处理 Facebook。您可以使用一个非常简单的库:https://github.com/pac4j/spring-security-pac4j 来验证 OAuth(Facebook、Twitter、Google...)、CAS、SAML、OpenID (Connect) 和 GAE。查看演示:https://github.com/pac4j/spring-security-pac4j-demo
【讨论】:
【参考方案2】:Daniel 能否请您详细说明您在哪里卡住了。我使用相同的堆栈来集成 facebook 登录。但我没有使用 Spring Social。我相信这不是必需的。
将 facebook 登录与现有登录集成的步骤。
-
在您的 jsp 中使用 facebook javascript plugin 进行 Facebook 登录。
一旦用户批准您的应用程序。 OAuth 生成一个身份验证令牌,使用该令牌通过图形 API 获取客户端的电子邮件 ID。
使用 Ajax 将电子邮件 ID 发送到服务器。
将发送到服务器端的电子邮件 ID 与数据库中的电子邮件 ID 进行比较。
如果电子邮件 ID 相同,请登录用户。
身份验证令牌是临时的,因此我发现将其发送到服务器端或保存在数据库中是没有意义的。它保存在客户端本地。并且 fb javascript 插件会处理它。这样就省去了实施 spring social facebook 的麻烦。
我看到您正在使用控制器进行 facebook 登录,这不是必需的,相信我使用 fb javascript 插件真的很简单。
【讨论】:
嗨,感谢您的回答。我的问题是将 Facebook 登录与 Spring Security Session 集成时。我看到有些人将它与 spring social 和 spring security 一起使用。但是我在尝试实现其中一个示例时遇到了问题。 Underdog 错过了这一点-您不应该获取在客户端生成的客户端的电子邮件 ID,因为它可以很容易地被其他一些电子邮件修改,因此不应该进入的人可以进入.返回 auth 用户令牌后,您应该将该令牌发送到服务器端,您需要在服务器端检查此令牌是否仍然是生成的令牌,正如 facebook 在此处 developers.facebook.com/docs/facebook-login/login-flow-for-web/… 所推荐的那样。一旦您确认这一点,您就可以将该 facebook 用户作为您存在的用户之一登录。以上是关于将 Spring Security 与 Facebook 登录集成的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security + Keycloak 授权:如何将端点与资源相关联?
将 spring-security 与 spring-webflux 一起使用时禁用 WebSession 创建
是否可以将 Spring Security 的 AOP 与 Java Security Manager 合并?
将 Spring Security 与 EJB 或 Spring 一起使用?