From d07908f71b2572dfd49c3bafe51440f08992aeb4 Mon Sep 17 00:00:00 2001 From: DOHA Date: Mon, 7 Nov 2016 21:07:06 +0200 Subject: [PATCH] add source code for Facebook login --- spring-social-login/pom.xml | 169 ++++++++++++++++++ .../java/org/baeldung/config/Application.java | 18 ++ .../org/baeldung/config/SecurityConfig.java | 61 +++++++ .../java/org/baeldung/config/WebConfig.java | 39 ++++ .../persistence/dao/UserRepository.java | 10 ++ .../org/baeldung/persistence/model/User.java | 55 ++++++ .../security/FacebookConnectionSignup.java | 28 +++ .../security/FacebookSignInAdapter.java | 21 +++ .../security/MyUserDetailsService.java | 34 ++++ .../src/main/resources/application.properties | 3 + .../src/main/resources/data.sql | 1 + .../src/main/resources/templates/index.html | 27 +++ .../src/main/resources/templates/login.html | 44 +++++ .../test/ApplicationIntegrationTest.java | 18 ++ 14 files changed, 528 insertions(+) create mode 100644 spring-social-login/pom.xml create mode 100644 spring-social-login/src/main/java/org/baeldung/config/Application.java create mode 100644 spring-social-login/src/main/java/org/baeldung/config/SecurityConfig.java create mode 100644 spring-social-login/src/main/java/org/baeldung/config/WebConfig.java create mode 100644 spring-social-login/src/main/java/org/baeldung/persistence/dao/UserRepository.java create mode 100644 spring-social-login/src/main/java/org/baeldung/persistence/model/User.java create mode 100644 spring-social-login/src/main/java/org/baeldung/security/FacebookConnectionSignup.java create mode 100644 spring-social-login/src/main/java/org/baeldung/security/FacebookSignInAdapter.java create mode 100644 spring-social-login/src/main/java/org/baeldung/security/MyUserDetailsService.java create mode 100644 spring-social-login/src/main/resources/application.properties create mode 100644 spring-social-login/src/main/resources/data.sql create mode 100644 spring-social-login/src/main/resources/templates/index.html create mode 100644 spring-social-login/src/main/resources/templates/login.html create mode 100644 spring-social-login/src/test/java/org/baeldung/test/ApplicationIntegrationTest.java diff --git a/spring-social-login/pom.xml b/spring-social-login/pom.xml new file mode 100644 index 0000000000..6e74b1c3d1 --- /dev/null +++ b/spring-social-login/pom.xml @@ -0,0 +1,169 @@ + + 4.0.0 + spring-social-login + + spring-social-login + war + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RELEASE + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + + org.springframework.security + spring-security-web + + + + org.springframework.security + spring-security-config + + + + org.springframework.security + spring-security-taglibs + + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity4 + + + + + org.springframework.social + spring-social-facebook + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + com.h2database + h2 + + + + + org.springframework.boot + spring-boot-starter-test + + + + org.springframework + spring-test + test + + + + junit + junit + test + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + + + spring-social-login + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-war-plugin + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*IntegrationTest.java + **/*LiveTest.java + + + + + + + + + integration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*LiveTest.java + + + **/*IntegrationTest.java + + + + + + + json + + + + + + + + + + 1.8 + 3.3.2 + + + \ No newline at end of file diff --git a/spring-social-login/src/main/java/org/baeldung/config/Application.java b/spring-social-login/src/main/java/org/baeldung/config/Application.java new file mode 100644 index 0000000000..cf6251a51e --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/config/Application.java @@ -0,0 +1,18 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@SpringBootApplication +@EnableJpaRepositories("org.baeldung.persistence.dao") +@EntityScan("org.baeldung.persistence.model") +public class Application extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} \ No newline at end of file diff --git a/spring-social-login/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-social-login/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..8e439653a9 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/config/SecurityConfig.java @@ -0,0 +1,61 @@ +package org.baeldung.config; + +import org.baeldung.security.FacebookSignInAdapter; +import org.baeldung.security.FacebookConnectionSignup; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.social.connect.ConnectionFactoryLocator; +import org.springframework.social.connect.UsersConnectionRepository; +import org.springframework.social.connect.mem.InMemoryUsersConnectionRepository; +import org.springframework.social.connect.web.ProviderSignInController; + +@Configuration +@EnableWebSecurity +@ComponentScan(basePackages = { "org.baeldung.security" }) +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private ConnectionFactoryLocator connectionFactoryLocator; + + @Autowired + private UsersConnectionRepository usersConnectionRepository; + + @Autowired + private FacebookConnectionSignup facebookConnectionSignup; + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http + .csrf().disable() + .authorizeRequests() + .antMatchers("/login*","/signin/**","/signup/**").permitAll() + .anyRequest().authenticated() + .and() + .formLogin().loginPage("/login").permitAll() + .and() + .logout(); + } // @formatter:on + + @Bean + // @Primary + public ProviderSignInController providerSignInController() { + ((InMemoryUsersConnectionRepository) usersConnectionRepository).setConnectionSignUp(facebookConnectionSignup); + return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new FacebookSignInAdapter()); + } +} \ No newline at end of file diff --git a/spring-social-login/src/main/java/org/baeldung/config/WebConfig.java b/spring-social-login/src/main/java/org/baeldung/config/WebConfig.java new file mode 100644 index 0000000000..8cfcd6cb41 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/config/WebConfig.java @@ -0,0 +1,39 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@EnableWebMvc +public class WebConfig extends WebMvcConfigurerAdapter { + + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Override + public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/").setViewName("forward:/index"); + registry.addViewController("/index"); + registry.addViewController("/login"); + } + + @Override + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } + +} \ No newline at end of file diff --git a/spring-social-login/src/main/java/org/baeldung/persistence/dao/UserRepository.java b/spring-social-login/src/main/java/org/baeldung/persistence/dao/UserRepository.java new file mode 100644 index 0000000000..679dd6c363 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/persistence/dao/UserRepository.java @@ -0,0 +1,10 @@ +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + + User findByUsername(final String username); + +} diff --git a/spring-social-login/src/main/java/org/baeldung/persistence/model/User.java b/spring-social-login/src/main/java/org/baeldung/persistence/model/User.java new file mode 100644 index 0000000000..a4cffc27d0 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/persistence/model/User.java @@ -0,0 +1,55 @@ +package org.baeldung.persistence.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class User { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column(nullable = false, unique = true) + private String username; + + private String password; + + public User() { + super(); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("User [id=").append(id).append(", username=").append(username).append(", password=").append(password).append("]"); + return builder.toString(); + } + +} diff --git a/spring-social-login/src/main/java/org/baeldung/security/FacebookConnectionSignup.java b/spring-social-login/src/main/java/org/baeldung/security/FacebookConnectionSignup.java new file mode 100644 index 0000000000..6a9e30d7d8 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/security/FacebookConnectionSignup.java @@ -0,0 +1,28 @@ +package org.baeldung.security; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; + +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.social.connect.Connection; +import org.springframework.social.connect.ConnectionSignUp; +import org.springframework.stereotype.Service; + +@Service +public class FacebookConnectionSignup implements ConnectionSignUp { + + @Autowired + private UserRepository userRepository; + + @Override + public String execute(Connection connection) { + System.out.println("signup === "); + final User user = new User(); + user.setUsername(connection.getDisplayName()); + user.setPassword(randomAlphabetic(8)); + userRepository.save(user); + return user.getUsername(); + } + +} diff --git a/spring-social-login/src/main/java/org/baeldung/security/FacebookSignInAdapter.java b/spring-social-login/src/main/java/org/baeldung/security/FacebookSignInAdapter.java new file mode 100644 index 0000000000..b861609a01 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/security/FacebookSignInAdapter.java @@ -0,0 +1,21 @@ +package org.baeldung.security; + +import java.util.Arrays; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.social.connect.Connection; +import org.springframework.social.connect.web.SignInAdapter; +import org.springframework.stereotype.Service; +import org.springframework.web.context.request.NativeWebRequest; + +@Service +public class FacebookSignInAdapter implements SignInAdapter { + @Override + public String signIn(String localUserId, Connection connection, NativeWebRequest request) { + System.out.println(" ====== Sign In adapter"); + SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(connection.getDisplayName(), null, Arrays.asList(new SimpleGrantedAuthority("FACEBOOK_USER")))); + return null; + } +} diff --git a/spring-social-login/src/main/java/org/baeldung/security/MyUserDetailsService.java b/spring-social-login/src/main/java/org/baeldung/security/MyUserDetailsService.java new file mode 100644 index 0000000000..5d0d5d793a --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/security/MyUserDetailsService.java @@ -0,0 +1,34 @@ +package org.baeldung.security; + +import java.util.Arrays; + +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service +public class MyUserDetailsService implements UserDetailsService { + + @Autowired + private UserRepository userRepository; + + public MyUserDetailsService() { + super(); + } + + // API + + @Override + public UserDetails loadUserByUsername(final String username) { + final User user = userRepository.findByUsername(username); + if (user == null) { + throw new UsernameNotFoundException(username); + } + return new org.springframework.security.core.userdetails.User(username, user.getPassword(), true, true, true, true, Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))); + } +} diff --git a/spring-social-login/src/main/resources/application.properties b/spring-social-login/src/main/resources/application.properties new file mode 100644 index 0000000000..2bd99d8239 --- /dev/null +++ b/spring-social-login/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.social.facebook.appId=1715784745414888 +spring.social.facebook.appSecret=abefd6497e9cc01ad03be28509617bf0 +spring.thymeleaf.cache=false \ No newline at end of file diff --git a/spring-social-login/src/main/resources/data.sql b/spring-social-login/src/main/resources/data.sql new file mode 100644 index 0000000000..3b26afef32 --- /dev/null +++ b/spring-social-login/src/main/resources/data.sql @@ -0,0 +1 @@ +insert into User (id, username, password) values (1,'john', '123'); \ No newline at end of file diff --git a/spring-social-login/src/main/resources/templates/index.html b/spring-social-login/src/main/resources/templates/index.html new file mode 100644 index 0000000000..8e1a8da60f --- /dev/null +++ b/spring-social-login/src/main/resources/templates/index.html @@ -0,0 +1,27 @@ + + + + +Spring Social Login + + + + + + +
+

Welcome, Username

+

User authorities

+
+ + \ No newline at end of file diff --git a/spring-social-login/src/main/resources/templates/login.html b/spring-social-login/src/main/resources/templates/login.html new file mode 100644 index 0000000000..41ad39332c --- /dev/null +++ b/spring-social-login/src/main/resources/templates/login.html @@ -0,0 +1,44 @@ + + + + +Spring Social Login + + + +
+
You have been logged out
+
There was an error, please try again
+ +

Login

+
+
+
+ + +
+
+
+ + +
+ +
+ +
+
+
+
+
+
+
+
+ + +
+
+ + +
+ + \ No newline at end of file diff --git a/spring-social-login/src/test/java/org/baeldung/test/ApplicationIntegrationTest.java b/spring-social-login/src/test/java/org/baeldung/test/ApplicationIntegrationTest.java new file mode 100644 index 0000000000..43aaea18b1 --- /dev/null +++ b/spring-social-login/src/test/java/org/baeldung/test/ApplicationIntegrationTest.java @@ -0,0 +1,18 @@ +package org.baeldung.test; + +import org.baeldung.config.Application; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT) +public class ApplicationIntegrationTest { + + @Test + public void whenLoadApplication_thenSuccess() { + + } +}