post-image

Login với Facebook trong Spring Boot

Social

Trong bài viết này chúng ta cùng tìm hiểu cách để Login với Facebook trong dự án SpringBoot. Chúng ta sẽ sử dụng đến Spring Social ở bài viết này.

Cài đặt thư viện

Đầu tiên chúng ta thêm những thư viện sau:

  • Với Maven chúng ta vào file porm.xml
<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-facebook</artifactId>
    <version>2.0.3.RELEASE</version>
</dependency>Code language: HTML, XML (xml)
  • Với Gradle chúng ta thêm vào file build.gradle
compile group: 'org.springframework.social', name: 'spring-social-facebook', version: '2.0.3.RELEASE'
Code language: JavaScript (javascript)

Cấu hình file SecurityConfig

Chúng ta sẽ cấu hình file SecurityConfig đơn giản như sau:

SecurityConfig.java

@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();
    } 
}Code language: PHP (php)

Cấu hình file application.properties

Chúng ta thêm đoạn cấu hình để sử dụng Facebook vào trong file application.properties như sau:

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

Trong đó YOUR_APP_ID và YOUR_APP_SECRET các bạn sẽ lấy ở trên trang https://developers.facebook.com  mình cũng đã hướng dẫn cách lấy mã tương tự ở bài viết ChatBot các bạn có thể tìm để xem lại.

Thêm cấu hình Facebook vào file SecurityConfig

Tiếp theo chúng ta sẽ thêm các config của Facebook sau vào trong file SecurityConfig

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);
    }
}Code language: PHP (php)

Ở đoạn code trên mình có thêm một số các config mới liên quan facebook:

  • Sử dụng ProviderSignInController để kích hoạt xác thực qua Facebook nên nó sẽ cần tới ConnectionFactoryLocator để đăng ký FacebookConnectionFactory với những thuộc tính chúng ta khai báo ở file appilcation.properties ở trên
  • Sử dụng SigninAdapter để xử lý nghiệp vụ login cho ứng dụng của chúng ta.
  • Sử dụng ConnectionSignUp  để xử lý đăng ký tài khoản mới đăng nhập Facebook lần đầu.

Sign-in Adapter

Có thể hiểu đơn giản đây là cầu nối trung gian giúp người dùng có thể sử dụng tài khoản Facebook để đăng nhập ứng dụng của chúng ta

	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;
    }
}Code language: PHP (php)

Connection Sign Up

Khi người dùng đăng nhập với Facebook lần đầu tiên, họ không có tài khoản trong ứng dụng của chúng ta.

Do đó chúng ta cần tạo tài khoản tự động cho họ; chúng ta sẽ sử dụng  ConnectionSignUp để tại tài khoản cho những người dùng đó

@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();
    }
}Code language: PHP (php)

Giao diện

Chúng ta tạo form login như sau ở đây mình sử dụng thymleaf

<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>Code language: HTML, XML (xml)

Và trang index.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>Code language: HTML, XML (xml)

Trang index sẽ hiển thị username người dùng đang đăng nhập và quyền của họ.

Leave a Reply

Your email address will not be published. Required fields are marked *