«1. Обзор

В этом руководстве мы сосредоточимся на добавлении новой учетной записи Facebook в существующее приложение формы входа.

Мы собираемся использовать поддержку Spring Social, чтобы взаимодействовать с Facebook и поддерживать чистоту и простоту.

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 extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) 
      throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .csrf().disable()
        .authorizeRequests()
        .antMatchers("/login*").permitAll()
        .anyRequest().authenticated()
        .and()
        .formLogin().loginPage("/login").permitAll();
    } 
}

Мы не собираемся тратить много времени на эту конфигурацию — если вы хотите лучше понять ее, взгляните на статья о входе в форму.

4. Свойства Facebook

Далее, давайте настроим свойства Facebook в нашем приложении. Настройки, убедитесь, что добавлена ​​платформа «Веб-сайт», а http://localhost:8080/ является «URL-адресом сайта»

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

5. Конфигурация безопасности — добавление Facebook

    Теперь давайте добавим новый способ аутентифицироваться в системе — управляется Facebook:

Давайте внимательно посмотрим на новую конфигурацию:

мы используем ProviderSignInController для включения аутентификации Facebook, для которой нужны две вещи: во-первых, зарегистрированный ConnectionFactoryLocator как FacebookConnectionFactory со свойствами Facebook, которые мы определили ранее. во-вторых, InMemoryUsersConnectionRepository. отправив POST на «/signin/facebook» — этот контроллер инициирует вход пользователя с помощью поставщика услуг Facebook, мы настраиваем SignInAdapter для обработки логики входа в наше приложение, и мы также настраиваем ConnectionSignUp для неявной обработки регистрации пользователей при их первой аутентификации в Facebook

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private FacebookConnectionSignup facebookConnectionSignup;

    @Value("${spring.social.facebook.appSecret}")
    String appSecret;
    
    @Value("${spring.social.facebook.appId}")
    String appId;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .authorizeRequests()
        .antMatchers("/login*","/signin/**","/signup/**").permitAll()
        ...
    } 

    @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);
    }
}

6. Адаптер входа в систему

    Проще говоря, этот адаптер представляет собой мост между контроллером, описанным выше, и управляет процессом входа пользователя в Facebook. – и наше конкретное локальное приложение:

Обратите внимание, что пользователи, вошедшие в систему с помощью Facebook, будут иметь роль FACEBOOK_USER, а пользователи, вошедшие в систему с помощью формы, будут иметь роль USER.

7. Регистрация подключения

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 в первый раз, у него нет существующей учетной записи в нашем приложении.

Это тот момент, когда нам нужно автоматически создать для них эту учетную запись; мы собираемся использовать ConnectionSignUp для управления логикой создания пользователя:

Как видите, мы создали учетную запись для нового пользователя, используя его DisplayName в качестве имени пользователя.

8. Внешний интерфейс

@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();
    }
}

Наконец, давайте взглянем на наш внешний интерфейс.

Теперь у нас будет поддержка этих двух потоков аутентификации – формы входа и Facebook – на нашей странице входа:

Наконец, вот index.html:

Обратите внимание, как на этой индексной странице отображаются имена пользователей и полномочия.

<html>
<body>
<div th:if="${param.logout}">You have been logged out</div>
<div th:if="${param.error}">There was an error, please try again</div>

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

Вот и все — теперь у нас есть два способа аутентификации в приложении.

<html>
<body>
<nav>
    <p sec:authentication="name">Username</p>      
    <a th:href="@{/logout}">Logout</a>                     
</nav>

<h1>Welcome, <span sec:authentication="name">Username</span></h1>
<p sec:authentication="authorities">User authorities</p>
</body>
</html>

9. Заключение

В этой быстрой статье мы узнали, как использовать spring-social-facebook для реализации вторичного потока аутентификации для нашего приложения.

И, конечно же, как всегда, исходный код полностью доступен на GitHub.

«

And of course, as always, the source code is fully available over on GitHub.