Spring Social 輔助登錄

Spring Security
Remote
1
10:30 PM · Nov 29 ,2025

1. 概述

在本教程中,我們將重點介紹如何向現有表單登錄應用添加新的 Facebook 登錄功能。

我們將使用 Spring Social 支持與 Facebook 交互,並保持簡潔明瞭。

注意: Spring Social 庫已棄用;我們可以查看 Spring Security 5 – OAuth2 Login,它提供基於 OAuth2 的社交登錄功能。

2. Maven 配置

首先,我們需要將 spring-social-facebook 依賴添加到我們的 pom.xml 中:

<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-facebook</artifactId>
    <version>2.0.3.RELEASE</version>
</dependency>

3. 安全配置 – 僅限表單登錄

我們首先從簡單的安全配置開始,這裏我們只使用基於表單的身份驗證:

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = { "com.baeldung.security" })
public class SecurityConfig {
    
    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public AuthenticationManager authManager(HttpSecurity http) throws Exception {
        return http.getSharedObject(AuthenticationManagerBuilder.class)
            .userDetailsService(userDetailsService)
            .and()
            .build();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf()
            .disable()
            .authorizeRequests()
            .antMatchers("/login*", "/signin/**", "/signup/**")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
            .logout();
        return http.build();
    }
}

我們不會花費太多時間來理解這個配置 – 如果你想更好地理解它,請查看錶單登錄文章。

4. Facebook 屬性

接下來,讓我們在我們的 application.properties 中配置 Facebook 屬性:

spring.social.facebook.appId=YOUR_APP_ID
spring.social.facebook.appSecret=YOUR_APP_SECRET

請注意:

  • 我們需要創建一個 Facebook 應用程序以獲取 appIdappSecret
  • 從 Facebook 應用程序設置中,請確保將“網站”平台和 http://localhost:8080/ 添加為“站點 URL”。

5. Security Config – Adding Facebook

Now, let’s add a new way to authenticate into the system – driven by Facebook:

public class SecurityConfig {

    @Autowired
    private FacebookConnectionSignup facebookConnectionSignup;

    @Value("${spring.social.facebook.appSecret}")
    String appSecret;
    
    @Value("${spring.social.facebook.appId}")
    String appId;
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
        .authorizeRequests()
        .antMatchers("/login*","/signin/**","/signup/**").permitAll()
        ...
        return http.build();
    } 

    @Bean
    public ProviderSignInController providerSignInController() {
        ConnectionFactoryLocator connectionFactoryLocator = 
            connectionFactoryLocator();
        UsersConnectionRepository usersConnectionRepository = 
            getUsersConnectionRepository(connectionFactoryLocator);
        ((InMemoryUsersConnectionRepository) usersConnectionRepository)
            .setConnectionSignUp(facebookConnectionSignup);
        return new ProviderSignInController(connectionFactoryLocator, 
            usersConnectionRepository, new FacebookSignInAdapter());
    }
    
    private ConnectionFactoryLocator connectionFactoryLocator() {
        ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
        registry.addConnectionFactory(new FacebookConnectionFactory(appId, appSecret));
        return registry;
    }
    
    private UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator 
        connectionFactoryLocator) {
        return new InMemoryUsersConnectionRepository(connectionFactoryLocator);
    }
}

Let’s carefully look at the new config:

    we’re using a ProviderSignInController to enable the Facebook authentication, which needs two things:
    first, a ConnectionFactoryLocator registered as a FacebookConnectionFactory with the Facebook properties we defined earlier.
    second, an InMemoryUsersConnectionRepository.
  • by sending a POST to “/signin/facebook” – this controller will initiate a user sign-in using the Facebook service provider
  • we’re setting up a SignInAdapter to handle the login logic in our application
  • and we also setting up a ConnectionSignUp to handle signing up users implicitly when they first authenticate with Facebook

6. Facebook 登錄適配器

簡單來説,這個適配器是連接上述控制器——驅動 Facebook 用户登錄流程——和我們本地應用程序的橋樑:

public class FacebookSignInAdapter implements SignInAdapter {
    @Override
    public String signIn(
      String localUserId, 
      Connection<?> connection, 
      NativeWebRequest request) {
        
        SecurityContextHolder.getContext().setAuthentication(
          new UsernamePasswordAuthenticationToken(
          connection.getDisplayName(), null, 
          Arrays.asList(new SimpleGrantedAuthority("FACEBOOK_USER"))));
        
        return null;
    }
}

請注意,使用 Facebook 登錄的用户將擁有角色 FACEBOOK_USER,而使用表單登錄的用户將擁有角色 USER

7. 連接註冊

當用户首次使用 Facebook 進行身份驗證時,他們沒有在我們應用程序中已存在的賬户。

這是我們需要自動為他們創建該賬户的時刻;我們將使用 ConnectionSignUp 來驅動該用户創建邏輯:

@Service
public class FacebookConnectionSignup implements ConnectionSignUp {

    @Autowired
    private UserRepository userRepository;

    @Override
    public String execute(Connection<?> connection) {
        User user = new User();
        user.setUsername(connection.getDisplayName());
        user.setPassword(randomAlphabetic(8));
        userRepository.save(user);
        return user.getUsername();
    }
}

正如你所看到的,我們為新用户創建了一個賬户 – 使用他們的 DisplayName 作為用户名。

8. 前端

最後,讓我們來查看我們的前端。

現在,我們將為這些兩個身份驗證流程 – 表單登錄和 Facebook – 在我們的登錄頁面提供支持:

<html>
<body>
<div th:if="${param.logout}">您已註銷</div>
<div th:if="${param.error}">發生錯誤,請重試</div>

<form th:action="@{/login}" method="POST" >
    <input type="text" name="username" />
    <input type="password" name="password" />
    <input type="submit" value="登錄" />
</form>
	
<form action="/signin/facebook" method="POST">
    <input type="hidden" name="scope" value="public_profile" />
    <input type="submit" value="使用 Facebook 登錄"/>
</form>
</body>
</html>

最後 – 這裏是 index.html

<html>
<body>
<nav>
    <p sec:authentication="name">用户名</p>      
    <a th:href="@{/logout}">登出</a>                     
</nav>

<h1>歡迎, <span sec:authentication="name">用户名</span></h1>
<p sec:authentication="authorities">用户權限</p>
</body>
</html>

注意,這個 index 頁面顯示用户名和權限。

而且,這就是全部 – 我們現在有兩方便驗證應用程序的方法。

9. 結論

在本文中,我們學習瞭如何使用 spring-social-facebook 來為我們的應用程序實現輔助身份驗證流程。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.