betacode

Социальный вход в Spring MVC с Spring Social Security

  1. Таблицы
  2. Модель логина
  3. Регистрация Oauth2
  4. Конфигурация web.xml и Maven
  5. Конфигурация Spring MVC и Security
  6. User, User Serivce, User DAO
  7. Классы для регистрации аккаунта (SignUp)
  8. Controller
  9. Страницы JSP
  10. Запуск приложения

1. Таблицы

Для начала, вам нужно создать таблицы:
** ORACLE **
-- Create table
create table USERCONNECTION
(
USERID         VARCHAR2(255) not null,
PROVIDERID     VARCHAR2(255) not null,
PROVIDERUSERID VARCHAR2(255) not null,
RANK           INTEGER not null,
DISPLAYNAME    VARCHAR2(255),
PROFILEURL     VARCHAR2(512),
IMAGEURL       VARCHAR2(512),
ACCESSTOKEN    VARCHAR2(255) not null,
SECRET         VARCHAR2(255),
REFRESHTOKEN   VARCHAR2(255),
EXPIRETIME     NUMBER(19)
) ;

-- Create/Recreate primary, unique and foreign key constraints
alter table USERCONNECTION
add primary key (USERID, PROVIDERID, PROVIDERUSERID) ;

-- Create/Recreate indexes
create unique index USERCONNECTIONRANK on USERCONNECTION (USERID, PROVIDERID, RANK) ;

----------------------------------------- Create table
create table USER_ACCOUNTS
(
ID         VARCHAR2(255) not null,
EMAIL      VARCHAR2(100) not null,
USER_NAME      VARCHAR2(100) not null,
FIRST_NAME VARCHAR2(100) not null,
LAST_NAME  VARCHAR2(100) not null,
PASSWORD   VARCHAR2(255),
ROLE       VARCHAR2(20) not null,
ENABLED    VARCHAR2(1) default 'Y' not null
) ;
-- Create/Recreate primary, unique and foreign key constraints
alter table USER_ACCOUNTS
add primary key (ID) ;
alter table USER_ACCOUNTS
  add constraint User_Account_UK1 unique (EMAIL);
alter table USER_ACCOUNTS
  add constraint User_Account_UK2 unique (USER_NAME);
** MYSQL/SQL SERVER **
-- Create table
create table USERCONNECTION
(
USERID         VARCHAR(255) not null,
PROVIDERID     VARCHAR(255) not null,
PROVIDERUSERID VARCHAR(255) not null,
RANK           INTEGER not null,
DISPLAYNAME    VARCHAR(255),
PROFILEURL     VARCHAR(512),
IMAGEURL       VARCHAR(512),
ACCESSTOKEN    VARCHAR(255) not null,
SECRET         VARCHAR(255),
REFRESHTOKEN   VARCHAR(255),
EXPIRETIME     BIGINT
) ;

-- Create/Recreate primary, unique and foreign key constraints
alter table USERCONNECTION
add primary key (USERID, PROVIDERID, PROVIDERUSERID) ;

-- Create/Recreate indexes
create unique index USERCONNECTIONRANK on USERCONNECTION (USERID, PROVIDERID, RANK) ;

-----------------------------------------
-- Create table
create table USER_ACCOUNTS
(
ID         VARCHAR(255) not null,
EMAIL      VARCHAR(100) not null,
USER_NAME      VARCHAR(100) not null,
FIRST_NAME VARCHAR(100) not null,
LAST_NAME  VARCHAR(100) not null,
PASSWORD   VARCHAR(255),
ROLE       VARCHAR(20) not null,
ENABLED    VARCHAR(1) default 'Y' not null
) ;
-- Create/Recreate primary, unique and foreign key constraints
alter table USER_ACCOUNTS
add primary key (ID) ;
alter table USER_ACCOUNTS
 add constraint User_Account_UK1 unique (EMAIL);
alter table USER_ACCOUNTS
 add constraint User_Account_UK2 unique (USER_NAME);
USERCONNECTION & USER_ACCOUNTS
Если у вас есть готовое приложение Web Spring, и вход в эту систему осуществляется через аккаунты сохраненные в таблице, как USER_ACCOUNTS. (Заметьте, что может структура вашей таблицы Users может отличаться от структуры этой таблицы).
Вы можете интегрировать функцию входа в систему через социальную сеть в ваш Website. Вам нужно создать таблицу USERCONNECTION. Заметьте, что структура данной таблицы предоставлена Spring Social Security API, поэтому insert, update данных в эту таблицу поддерживается этим API. Но вы так же можете кастомизировать его структуру.
Примечание: insert, update в таблицу USERCONNECTION выполняется классом JdbcUsersConnectionRepository в Spring Social Security API.
Пример данных:

2. Модель логина

В случае, когда пользователь входит в систему через социальную сеть, ваше приложение требует разрешение на получение доступа к базовой информации (имя, электронная почта, ..). Если пользователь не согласен, то программа перенаправляет к странице /signin, чтобы пользователь вошел в систему обычным способом.
В случае пользователь не разрешает приложению получать его базовую информацию, есть 2 модели работы, иллюстрированные ниже:
Модель 1 : Отображение страницы регистрации после логина в социальную сеть
После того, как пользователь входит в систему через социальную сеть, у вас будет UserProfile, это объект хранения базовой информации пользователя и информации социальной сети, вы можете найти userID в таблице USERCONNECTION, соответствующая UserProfile, и найти запись USER_ACCOUNTS, соответствующая userID, Если нет соответствующей записи в таблице USER_ACCOUNTS, то перенаправляется к странице регистрации.

После регистрации пользователя, создается запись USER_ACCOUNTS, одновременно создается запись USERCONNECTION. И автоматически входит в систему вебсайта.
Модель 2: Автоматическое создание аккаунта поле логина, с помощью соцальной сети.
Эта модель почти похожа на Модель 1 выше, если не находится запись USERCONNECTIONS соответствующая UserProfile, создается запись User_Accounts, одновременно создается запись USERCONNECTION.

3. Регистрация Oauth2

Если вы хотите войти в систему используя Google вам нужно иметь Client ID, и Password и объявить Redirect URL к которому ваше приложение может перенаправить, когда пользователь успешно вошел в Google. Смотрите подробную инструкцию по ссылке:
Индентично с Facebook вам нужно создать Facebook Developer Application и App ID, как и объявить Redirect URL к которому ваше приложение может перенаправить, когда пользователь успешно вошел в Facebook. Смотрите подробную инструкцию по ссылке:

4. Конфигурация web.xml и Maven

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 id="WebApp_ID" version="3.0">

 <display-name>Spring Social Security</display-name>
 

</web-app>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
               http://maven.apache.org/maven-v4_0_0.xsd">

   <modelVersion>4.0.0</modelVersion>
   <groupId>org.o7planning</groupId>
   <artifactId>SpringMVCSocialJdbc</artifactId>
   <packaging>war</packaging>
   <version>0.0.1-SNAPSHOT</version>
   <name>SpringMVCSocialJdbc Maven Webapp</name>
   <url>http://maven.apache.org</url>




   <properties>
       <!-- Generic properties -->
       <java.version>1.7</java.version>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
   </properties>


   <repositories>
       <!-- Repository for ORACLE JDBC Driver -->
       <repository>
           <id>codelds</id>
           <url>https://code.lds.org/nexus/content/groups/main-repo</url>
       </repository>
   </repositories>

   <dependencies>

       <!-- Spring framework START -->
       <!-- http://mvnrepository.com/artifact/org.springframework/spring-core -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-core</artifactId>
           <version>4.2.5.RELEASE</version>
       </dependency>

       <!-- http://mvnrepository.com/artifact/org.springframework/spring-web -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-web</artifactId>
           <version>4.2.5.RELEASE</version>
       </dependency>

       <!-- http://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-webmvc</artifactId>
           <version>4.2.5.RELEASE</version>
       </dependency>



       <!-- http://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-jdbc</artifactId>
           <version>4.2.5.RELEASE</version>
       </dependency>


       <!-- Spring framework END -->


       <!-- Spring Security Artifacts - START -->
       <!-- http://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
       <dependency>
           <groupId>org.springframework.security</groupId>
           <artifactId>spring-security-web</artifactId>
           <version>4.0.4.RELEASE</version>
       </dependency>

       <!-- http://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
       <dependency>
           <groupId>org.springframework.security</groupId>
           <artifactId>spring-security-config</artifactId>
           <version>4.0.4.RELEASE</version>
       </dependency>

       <!-- http://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
       <dependency>
           <groupId>org.springframework.security</groupId>
           <artifactId>spring-security-taglibs</artifactId>
           <version>4.1.0.RELEASE</version>
       </dependency>

       <!-- Spring Security Artifacts - END -->

       <!-- Jstl for jsp page -->
       <!-- http://mvnrepository.com/artifact/javax.servlet/jstl -->
       <dependency>
           <groupId>javax.servlet</groupId>
           <artifactId>jstl</artifactId>
           <version>1.2</version>
       </dependency>

       <!-- Servlet API -->
       <!-- http://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
       <dependency>
           <groupId>javax.servlet</groupId>
           <artifactId>javax.servlet-api</artifactId>
           <version>3.1.0</version>
           <scope>provided</scope>
       </dependency>

       <!-- JSP API -->
       <!-- http://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
       <dependency>
           <groupId>javax.servlet.jsp</groupId>
           <artifactId>jsp-api</artifactId>
           <version>2.2</version>
           <scope>provided</scope>
       </dependency>

       <!-- MySQL JDBC driver -->
       <!-- http://mvnrepository.com/artifact/mysql/mysql-connector-java -->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>5.1.34</version>
       </dependency>

       <!-- Oracle JDBC driver -->
       <dependency>
           <groupId>com.oracle</groupId>
           <artifactId>ojdbc6</artifactId>
           <version>11.2.0.3</version>
       </dependency>

       <!-- SQLServer JDBC driver (JTDS) -->
       <!-- http://mvnrepository.com/artifact/net.sourceforge.jtds/jtds -->
       <dependency>
           <groupId>net.sourceforge.jtds</groupId>
           <artifactId>jtds</artifactId>
           <version>1.3.1</version>
       </dependency>




       <!-- http://mvnrepository.com/artifact/org.springframework.social/spring-social-config -->
       <dependency>
           <groupId>org.springframework.social</groupId>
           <artifactId>spring-social-config</artifactId>
           <version>1.1.4.RELEASE</version>
       </dependency>

       <!-- http://mvnrepository.com/artifact/org.springframework.social/spring-social-core -->
       <dependency>
           <groupId>org.springframework.social</groupId>
           <artifactId>spring-social-core</artifactId>
           <version>1.1.4.RELEASE</version>
       </dependency>

       <!-- http://mvnrepository.com/artifact/org.springframework.social/spring-social-security -->
       <dependency>
           <groupId>org.springframework.social</groupId>
           <artifactId>spring-social-security</artifactId>
           <version>1.1.4.RELEASE</version>
       </dependency>

       <!-- http://mvnrepository.com/artifact/org.springframework.social/spring-social-web -->
       <dependency>
           <groupId>org.springframework.social</groupId>
           <artifactId>spring-social-web</artifactId>
           <version>1.1.4.RELEASE</version>
       </dependency>

       <!-- http://mvnrepository.com/artifact/org.springframework.social/spring-social-facebook -->
       <dependency>
           <groupId>org.springframework.social</groupId>
           <artifactId>spring-social-facebook</artifactId>
           <version>2.0.3.RELEASE</version>
           <exclusions>
               <exclusion>
                   <artifactId>spring-social-core</artifactId>
                   <groupId>org.springframework.social</groupId>
               </exclusion>
               <exclusion>
                   <artifactId>spring-social-config</artifactId>
                   <groupId>org.springframework.social</groupId>
               </exclusion>
           </exclusions>
       </dependency>

       <!-- http://mvnrepository.com/artifact/org.springframework.social/spring-social-google -->
       <dependency>
           <groupId>org.springframework.social</groupId>
           <artifactId>spring-social-google</artifactId>
           <version>1.0.0.RELEASE</version>
       </dependency>


       <!-- http://mvnrepository.com/artifact/org.springframework.social/spring-social-twitter -->
       <dependency>
           <groupId>org.springframework.social</groupId>
           <artifactId>spring-social-twitter</artifactId>
           <version>1.1.2.RELEASE</version>
       </dependency>

       <!-- http://mvnrepository.com/artifact/org.springframework.social/spring-social-linkedin -->
       <dependency>
           <groupId>org.springframework.social</groupId>
           <artifactId>spring-social-linkedin</artifactId>
           <version>1.0.2.RELEASE</version>
       </dependency>

        <!-- Email validator,... -->
        <!-- http://mvnrepository.com/artifact/commons-validator/commons-validator -->
        <dependency>
            <groupId>commons-validator</groupId>
            <artifactId>commons-validator</artifactId>
            <version>1.5.0</version>
        </dependency>

   </dependencies>

 <build>
     <finalName>SpringMVCSocialJdbc</finalName>
     <plugins>
   
         <!-- Config: Maven Tomcat Plugin -->
         <!-- http://mvnrepository.com/artifact/org.apache.tomcat.maven/tomcat7-maven-plugin -->
         <plugin>
             <groupId>org.apache.tomcat.maven</groupId>
             <artifactId>tomcat7-maven-plugin</artifactId>
             <version>2.2</version>
             <!-- Config: contextPath and Port (Default: /SpringMVCSocialJdbc : 8080) -->
             <!--
             <configuration>
                 <path>/</path>
                 <port>8899</port>
             </configuration>
             -->  
         </plugin>
     </plugins>
 </build>      

</project>

5. Конфигурация Spring MVC и Security

ApplicationContextConfig.java
package org.o7planning.socialsecurity.config;

import javax.sql.DataSource;

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.context.annotation.PropertySource;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan("org.o7planning.socialsecurity.*")
@EnableTransactionManagement
// Load to Environment.
@PropertySource("classpath:datasource-cfg.properties")
public class ApplicationContextConfig {

   // The Environment class serves as the property holder
   // and stores all the properties loaded by the @PropertySource

   // Lưu trữ các giá thuộc tính load bởi @PropertySource.
   @Autowired
   private Environment env;



   @Bean
   public ResourceBundleMessageSource messageSource() {
       ResourceBundleMessageSource rb = new ResourceBundleMessageSource();
       // Load property in message/validator.properties
       rb.setBasenames(new String[] { "messages/validator" });
       return rb;
   }

   @Bean(name = "viewResolver")
   public InternalResourceViewResolver getViewResolver() {
       InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
       viewResolver.setPrefix("/WEB-INF/pages/");
       viewResolver.setSuffix(".jsp");
       return viewResolver;
   }

   @Bean(name = "dataSource")
   public DataSource getDataSource() {
       DriverManagerDataSource dataSource = new DriverManagerDataSource();

       // See: datasouce-cfg.properties
       // Xem: datasouce-cfg.properties
       dataSource.setDriverClassName(env.getProperty("ds.database-driver"));
       dataSource.setUrl(env.getProperty("ds.url"));
       dataSource.setUsername(env.getProperty("ds.username"));
       dataSource.setPassword(env.getProperty("ds.password"));

       System.out.println("## getDataSource: " + dataSource);

       return dataSource;
   }

   // Transaction Manager
   @Autowired
   @Bean(name = "transactionManager")
   public DataSourceTransactionManager getTransactionManager(DataSource dataSource) {
       DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);

       return transactionManager;
   }
 
 
}
SpringWebAppInitializer.java
package org.o7planning.socialsecurity.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class SpringWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(ApplicationContextConfig.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDispatcher",
                new DispatcherServlet(appContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

}
WebMvcConfig.java
package org.o7planning.socialsecurity.config;

import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
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.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

  private static final Charset UTF8 = Charset.forName("UTF-8");

  // Config UTF-8 Encoding.
  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
      StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
      stringConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "plain", UTF8)));
      converters.add(stringConverter);

      // Add other converters ...
  }

  // Static Resource Config
  // equivalents for <mvc:resources/> tags
  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
      registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
      registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
      registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
  }

  // Equivalent for <mvc:default-servlet-handler/> tag
  @Override
  public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
      configurer.enable();
  }

}
Информация базы данных:
datasource-cfg.properties (** For ORACLE DB)
# DataSource

ds.database-driver=oracle.jdbc.driver.OracleDriver
ds.url=jdbc:oracle:thin:@localhost:1521:db12c
ds.username=oauth2
ds.password=oauth2
datasource-cfg.properties (** For MYSQL DB)
# DataSource

ds.database-driver=com.mysql.jdbc.Driver
ds.url=jdbc:mysql://localhost:3306/oauth2
ds.username=root
ds.password=12345
datasource-cfg.properties (** For SQL SERVER DB)
# DataSource

ds.database-driver=net.sourceforge.jtds.jdbc.Driver
ds.url=jdbc:jtds:sqlserver://localhost:1433/simplehr;instance=SQLEXPRESS
ds.username=oauth2
ds.password=12345
Конфигурация Security:
SpringSecurityInitializer.java
package org.o7planning.socialsecurity.config;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

// Config: Spring Security Filter.
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {

    // Do nothing

}
WebSecurityConfig.java
package org.o7planning.socialsecurity.config;

import org.o7planning.socialsecurity.service.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
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.security.SpringSocialConfigurer;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

   @Autowired
   private MyUserDetailsService myUserDetailsService;

   @Autowired
   public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

       // Set Service load Users in Database
       auth.userDetailsService(myUserDetailsService);
   }

   @Override
   protected void configure(HttpSecurity http) throws Exception {

       http.csrf().disable();

       // The pages does not require login
       http.authorizeRequests().antMatchers("/", "/signup", "/login", "/logout").permitAll();

       // /userInfo page requires login as ROLE_USER  
       // If no login, it will redirect to /login page.
       http.authorizeRequests().antMatchers("/userInfo").access("hasRole('ROLE_USER')");

       // Form Login config
       http.authorizeRequests().and().formLogin()//
               // Submit URL of login page.
               .loginProcessingUrl("/j_spring_security_check") // Submit URL
               .loginPage("/login")//
               .defaultSuccessUrl("/userInfo")//
               .failureUrl("/login?error=true")//
               .usernameParameter("username")//
               .passwordParameter("password");

       // Logout Config
       http.authorizeRequests().and().logout().logoutUrl("/logout").logoutSuccessUrl("/");

       // Spring Social Config.
       http.apply(new SpringSocialConfigurer())
               //
               .signupUrl("/signup");

   }
   

   // This bean is load the user specific data when form login is used.
   @Override
   public UserDetailsService userDetailsService() {
       return myUserDetailsService;
   }
   
}
Конфигурация Spring Social Security:
SocialConfig.java
package org.o7planning.socialsecurity.config;

import javax.sql.DataSource;

import org.o7planning.socialsecurity.dao.MyUserAccountDAO;
import org.o7planning.socialsecurity.signup.MyConnectionSignUp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.social.UserIdSource;
import org.springframework.social.config.annotation.ConnectionFactoryConfigurer;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurer;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.ConnectionRepository;
import org.springframework.social.connect.ConnectionSignUp;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository;
import org.springframework.social.connect.web.ConnectController;
import org.springframework.social.facebook.connect.FacebookConnectionFactory;
import org.springframework.social.google.connect.GoogleConnectionFactory;
import org.springframework.social.linkedin.connect.LinkedInConnectionFactory;
import org.springframework.social.security.AuthenticationNameUserIdSource;
import org.springframework.social.twitter.connect.TwitterConnectionFactory;

@Configuration
@EnableSocial
// Load to Environment.
@PropertySource("classpath:social-cfg.properties")
public class SocialConfig implements SocialConfigurer {

  private boolean autoSignUp = false;

  @Autowired
  private DataSource dataSource;

  @Autowired
  private MyUserAccountDAO myUserAccountDAO;
 
 

  // @env: Read properties file config by @PropertySource.
  @Override
  public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {

      // Twitter
      TwitterConnectionFactory tfactory = new TwitterConnectionFactory(//
              env.getProperty("twitter.consumer.key"), //
              env.getProperty("twitter.consumer.secret"));

      // tfactory.setScope(env.getProperty("twitter.scope"));
     
      cfConfig.addConnectionFactory(tfactory);

      // Facebook
      FacebookConnectionFactory ffactory = new FacebookConnectionFactory(//
              env.getProperty("facebook.app.id"), //
              env.getProperty("facebook.app.secret"));
     
     
      ffactory.setScope(env.getProperty("facebook.scope"));
     
      // auth_type=reauthenticate

      cfConfig.addConnectionFactory(ffactory);

      // Linkedin
      LinkedInConnectionFactory lfactory = new LinkedInConnectionFactory(//
              env.getProperty("linkedin.consumer.key"), //
              env.getProperty("linkedin.consumer.secret"));

      lfactory.setScope(env.getProperty("linkedin.scope"));
     
      cfConfig.addConnectionFactory(lfactory);

     
      // Google
      GoogleConnectionFactory gfactory = new GoogleConnectionFactory(//
              env.getProperty("google.client.id"), //
              env.getProperty("google.client.secret"));

      gfactory.setScope(env.getProperty("google.scope"));
     
      cfConfig.addConnectionFactory(gfactory);
  }

  // The UserIdSource determines the userID of the user.
  @Override
  public UserIdSource getUserIdSource() {
      return new AuthenticationNameUserIdSource();
  }

  // Read and insert to USERCONNECTION.
  @Override
  public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {

      // org.springframework.social.security.SocialAuthenticationServiceRegistry
      JdbcUsersConnectionRepository usersConnectionRepository = new JdbcUsersConnectionRepository(dataSource,
              connectionFactoryLocator,

              Encryptors.noOpText());

      if (autoSignUp) {
          // Config to:
          // After login to social.
          // Automatically create corresponding USER_ACCOUNT if not already.
          ConnectionSignUp connectionSignUp = new MyConnectionSignUp(myUserAccountDAO);
          usersConnectionRepository.setConnectionSignUp(connectionSignUp);
      } else {
          // Config to:
          // After login to social.
          // If USER_ACCOUNTS does not exists
          // Redirect to register page.
          usersConnectionRepository.setConnectionSignUp(null);
      }
      return usersConnectionRepository;
  }

  // This bean manages the connection flow between the account provider and
  // the example application.
  @Bean
  public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator, //
          ConnectionRepository connectionRepository) {
      return new ConnectController(connectionFactoryLocator, connectionRepository);
  }
 
 
}
Конфигурация социальной сети:
social-cfg.properties
# Twitter
# http://localhost:8080/SpringMVCSocialJdbc/auth/twitter

twitter.consumer.key=
twitter.consumer.secret=
twitter.scope=
       
# Facebook
# http://localhost:8080/SpringMVCSocialJdbc/auth/facebook

facebook.app.id=1084911261562762
facebook.app.secret=81a324fdbc4cade1ee25523c7bff58b3
facebook.scope=public_profile,email

# Linkedin
# http://localhost:8080/SpringMVCSocialJdbc/auth/linkedin

linkedin.consumer.key=...
linkedin.consumer.secret=...
linkedin.scope=

# Google
# http://localhost:8080/SpringMVCSocialJdbc/auth/google

google.client.id=160790488111-he5fn6rq0foqg05te70dk25gifeoum9s.apps.googleusercontent.com
google.client.secret=VILTmX1UjOnyw2_meYvDQEdl
google.scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile
Примечание: Чтобы войти в социальную сеть Google, вам нужно включить (enable) Google+ API:

6. User, User Serivce, User DAO

MyUserAccount это класс, который представляет запись в таблице USER_ACCOUNTS в DB.
MyUserAccount.java
package org.o7planning.socialsecurity.model;

public class MyUserAccount {

   public static final String ROLE_USER = "ROLE_USER";

   private String id;
   private String email;
   private String userName;

   private String firstName;
   private String lastName;
   private String password;
   private String role;

   public MyUserAccount() {

   }

   public MyUserAccount(String id, String email,String userName, String firstName, //
           String lastName, String password, //
           String role) {
       this.id = id;
       this.email = email;
       this.userName= userName;
       this.firstName = firstName;
       this.lastName = lastName;
       this.password = password;
       this.role = role;
   }

   public String getId() {
       return id;
   }

   public void setId(String id) {
       this.id = id;
   }

   public String getEmail() {
       return email;
   }

   public void setEmail(String email) {
       this.email = email;
   }

   public String getUserName() {
       return userName;
   }

   public void setUserName(String userName) {
       this.userName = userName;
   }

   public String getFirstName() {
       return firstName;
   }

   public void setFirstName(String firstName) {
       this.firstName = firstName;
   }

   public String getLastName() {
       return lastName;
   }

   public void setLastName(String lastName) {
       this.lastName = lastName;
   }

   public String getPassword() {
       return password;
   }

   public void setPassword(String password) {
       this.password = password;
   }

   public String getRole() {
       return role;
   }

   public void setRole(String role) {
       this.role = role;
   }

}
MyUserAccountMapper это класс помогающий отображать (mapping) между полями (field) класса MyUserAccount и столбцами таблицы USER_ACCOUNTS.
MyUserAccountMapper.java
package org.o7planning.socialsecurity.mapper;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.o7planning.socialsecurity.model.MyUserAccount;
import org.springframework.jdbc.core.RowMapper;

public class MyUserAccountMapper implements RowMapper<MyUserAccount> {

    @Override
    public MyUserAccount mapRow(ResultSet rs, int rowNum) throws SQLException {

        String id = rs.getString("id");
 
        String email = rs.getString("email");
        String userName= rs.getString("user_name");
        String firstName = rs.getString("first_name");
        String lastName = rs.getString("last_name");
        String password = rs.getString("password");
        String role = rs.getString("role");

        return new MyUserAccount(id, email,userName, firstName, //
                lastName, password, //
                role );
    }

}
MyUserAccountDAO.java
package org.o7planning.socialsecurity.dao;

import java.util.UUID;

import javax.sql.DataSource;

import org.o7planning.socialsecurity.form.MyUserAccountForm;
import org.o7planning.socialsecurity.mapper.MyUserAccountMapper;
import org.o7planning.socialsecurity.model.MyUserAccount;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionKey;
import org.springframework.social.connect.UserProfile;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Transactional
public class MyUserAccountDAO extends JdbcDaoSupport {

   @Autowired
   public MyUserAccountDAO(DataSource dataSource) {
       this.setDataSource(dataSource);
   }

   public MyUserAccount findById(String id) {
       String sql = "Select id,email,user_name, first_name,last_name,"//
               + " password,role"//
               + " from User_Accounts u "//
               + " where id = ? ";
       Object[] params = new Object[] { id };
       MyUserAccountMapper mapper = new MyUserAccountMapper();
       try {
           MyUserAccount userInfo = this.getJdbcTemplate().queryForObject(sql, params, mapper);
           return userInfo;
       } catch (EmptyResultDataAccessException e) {
           return null;
       }
   }

   public MyUserAccount findByEmail(String email) {
       String sql = "Select id, email,user_name,first_name,last_name,"//
               + " password,role"//
               + " from User_Accounts u "//
               + " where email = ? ";
       Object[] params = new Object[] { email };
       MyUserAccountMapper mapper = new MyUserAccountMapper();
       try {
           MyUserAccount userInfo = this.getJdbcTemplate().queryForObject(sql, params, mapper);
           return userInfo;
       } catch (EmptyResultDataAccessException e) {
           return null;
       }
   }

   public MyUserAccount findByUserName(String userName) {
       String sql = "Select id, email,user_name,first_name,last_name,"//
               + " password,role"//
               + " from User_Accounts u "//
               + " where user_name = ? ";
       Object[] params = new Object[] { userName };
       MyUserAccountMapper mapper = new MyUserAccountMapper();
       try {
           MyUserAccount userInfo = this.getJdbcTemplate().queryForObject(sql, params, mapper);
           return userInfo;
       } catch (EmptyResultDataAccessException e) {
           return null;
       }
   }

   public MyUserAccount registerNewUserAccount(MyUserAccountForm accountForm) {
       String sql = "Insert into User_Accounts "//
               + " (id, email,user_name,first_name,last_name,password,role) "//
               + " values (?,?,?,?,?,?,?) ";

       // Random string with 36 characters.
       String id = UUID.randomUUID().toString();

       this.getJdbcTemplate().update(sql, id, accountForm.getEmail(), //
               accountForm.getUserName(), //
               accountForm.getFirstName(), accountForm.getLastName(), //
               accountForm.getPassword(), MyUserAccount.ROLE_USER);
       return findById(id);
   }

   // Auto Create USER_ACCOUNTS.
   public MyUserAccount createUserAccount(Connection<?> connection) {

       ConnectionKey key = connection.getKey();
       // (facebook,12345), (google,123) ...

       System.out.println("key= (" + key.getProviderId() + "," + key.getProviderUserId() + ")");

       UserProfile userProfile = connection.fetchUserProfile();

       String email = userProfile.getEmail();
       MyUserAccount account = this.findByEmail(email);
       if (account != null) {
           return account;
       }

       // Create User_Account.
       String sql = "Insert into User_Accounts "//
               + " (id, email,user_name,first_name,last_name,password,role) "//
               + " values (?,?,?,?,?,?,?) ";

       // Random string with 36 characters.
       String id = UUID.randomUUID().toString();
       
       String userName_prefix = userProfile.getFirstName().trim().toLowerCase()//
                           +"_"+ userProfile.getLastName().trim().toLowerCase();
       
       String userName = this.findAvailableUserName(userName_prefix);

       this.getJdbcTemplate().update(sql, id, email, userName, //
               userProfile.getFirstName(), userProfile.getLastName(), //
               "123", MyUserAccount.ROLE_USER);
       return findById(id);
   }

   private String findAvailableUserName(String userName_prefix) {
       MyUserAccount account = this.findByUserName(userName_prefix);
       if (account == null) {
           return userName_prefix;
       }
       int i = 0;
       while (true) {
           String userName = userName_prefix + "_" + i++;
           account = this.findByUserName(userName);
           if (account == null) {
               return userName;
           }
       }
   }

}
MySocialUserDetails это класс выполняющий интерфейс SocialUserDetails, заметьте, что SocialUserDetails это расширенный интерфейс из интерфейса UserDetails. Логин через социальную сеть используя Spring MVC Social API на самом деле основывается на Spring Security API.
MySocialUserDetails.java
package org.o7planning.socialsecurity.user;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.o7planning.socialsecurity.model.MyUserAccount;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.social.security.SocialUserDetails;

public class MySocialUserDetails implements SocialUserDetails {

    private static final long serialVersionUID = -5246117266247684905L;

    private List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
    private MyUserAccount myUserAccount;

    public MySocialUserDetails(MyUserAccount myUserAccount) {
        this.myUserAccount = myUserAccount;
        String role = myUserAccount.getRole();

        GrantedAuthority grant = new SimpleGrantedAuthority(role);
        this.list.add(grant);
    }

    @Override
    public String getUserId() {
        return this.myUserAccount.getId();
    }

    @Override
    public String getUsername() {
        return myUserAccount.getUserName();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return list;
    }

    @Override
    public String getPassword() {
        return myUserAccount.getPassword();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

}
MyUserDetailsService это сервис используемый Spring Security API чтобы получать информацию пользователя из базы данных.
MyUserDetailsService.java
package org.o7planning.socialsecurity.service;

import org.o7planning.socialsecurity.dao.MyUserAccountDAO;
import org.o7planning.socialsecurity.model.MyUserAccount;
import org.o7planning.socialsecurity.user.MySocialUserDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.social.security.SocialUserDetails;
import org.springframework.stereotype.Service;

// Service to Get user info from Database.
@Service
public class MyUserDetailsService implements UserDetailsService {

  @Autowired
  private MyUserAccountDAO myUserAccountDAO;

  public MyUserDetailsService() {

  }

  // (This method is used by Spring Security API).
  @Override
  public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {

      MyUserAccount myUserAccount = myUserAccountDAO.findByUserName(userName);

      if (myUserAccount == null) {
          throw new UsernameNotFoundException("No user found with userName: " + userName);
      }
      // Note: SocialUserDetails extends UserDetails.
      SocialUserDetails principal = new MySocialUserDetails(myUserAccount);

      return principal;
  }

}
SocialUserDetailsService это сервис используемый Spring Social Security API, для загрузки информации пользователя (который вошли в систему через социальную сеть) из базы данных.
Spring Social Security API это API основывающийся на Spring Security API, не заменяет Spring Security API.
MySocialUserDetailsService.java
package org.o7planning.socialsecurity.service;

import org.o7planning.socialsecurity.dao.MyUserAccountDAO;
import org.o7planning.socialsecurity.model.MyUserAccount;
import org.o7planning.socialsecurity.user.MySocialUserDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.social.security.SocialUserDetails;
import org.springframework.social.security.SocialUserDetailsService;
import org.springframework.stereotype.Service;

@Service
public class MySocialUserDetailsService implements SocialUserDetailsService {
   
   
   @Autowired
   private MyUserAccountDAO myUserAccountDAO;

   // Loads the UserDetails by using the userID of the user.
   // (This method Is used by Spring Security API).
   @Override
   public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException, DataAccessException {

       MyUserAccount account= myUserAccountDAO.findById(userId);
       
       MySocialUserDetails userDetails= new MySocialUserDetails(account);
       
       return userDetails;
   }

}

7. Классы для регистрации аккаунта (SignUp)

Как я упоминал выше. После логина через социальную сеть, если информация пользователя не существует в базе данных приложения, она создастся автоматически или перенаправится к странице, позволяющей пользователю вводить информацию аккаунта.
В случае если вы хотите автомитически создать запись USER_ACCOUNTS & USERCONNECTION, вам нужно записать класс выполняющий интерфейс ConnectionSignUp.
MyConnectionSignUp.java
package org.o7planning.socialsecurity.signup;

import org.o7planning.socialsecurity.dao.MyUserAccountDAO;
import org.o7planning.socialsecurity.model.MyUserAccount;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionSignUp;

public class MyConnectionSignUp implements ConnectionSignUp {

    private MyUserAccountDAO myUserAccountDAO;

    public MyConnectionSignUp(MyUserAccountDAO myUserAccountDAO) {
        this.myUserAccountDAO = myUserAccountDAO;
    }

    // After login Social.
    // This method is called to create a USER_ACCOUNTS record
    // if it does not exists.
    @Override
    public String execute(Connection<?> connection) {
       

        MyUserAccount account=    myUserAccountDAO.createUserAccount(connection);
        return account.getId();
    }

}

 
..
MyUserAccountValidator.java
package org.o7planning.socialsecurity.validator;

import org.apache.commons.validator.routines.EmailValidator;
import org.o7planning.socialsecurity.dao.MyUserAccountDAO;
import org.o7planning.socialsecurity.form.MyUserAccountForm;
import org.o7planning.socialsecurity.model.MyUserAccount;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

@Component
public class MyUserAccountValidator implements Validator {

    // common-validator library.
    private EmailValidator emailValidator = EmailValidator.getInstance();

    @Autowired
    private MyUserAccountDAO myUserAccountDAO;

    @Override
    public boolean supports(Class<?> clazz) {
        return clazz == MyUserAccountForm.class;
    }

    @Override
    public void validate(Object target, Errors errors) {
       
        MyUserAccountForm form = (MyUserAccountForm) target;
         
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "", "Email is required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "userName", "", "User name is required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "", "First name is required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "", "Last name is required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "", "Password is required");

        if (errors.hasErrors()) {
            return;
        }

        if (!emailValidator.isValid(form.getEmail())) {
             
            errors.rejectValue("email", "", "Email is not valid");
            return;
        }

        MyUserAccount userAccount = myUserAccountDAO.findByUserName(form.getUserName());
        if (userAccount != null) {
            if (form.getId() == null) {
                errors.rejectValue("userName", "", "User name is not available");
                return;
            } else if (!form.getId().equals(userAccount.getId())) {
                errors.rejectValue("userName", "", "User name is not available");
                return;
            }
        }

        userAccount = myUserAccountDAO.findByEmail(form.getEmail());
        if (userAccount != null) {
            if (form.getId() == null) {
                errors.rejectValue("email", "", "Email is not available");
                return;
            } else if (!form.getId().equals(userAccount.getId())) {
                errors.rejectValue("email", "", "Email is not available");
                return;
            }
        }
    }

}
MyUserAccountForm.java
package org.o7planning.socialsecurity.form;

import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionKey;
import org.springframework.social.connect.UserProfile;

public class MyUserAccountForm {

    private String id;
    private String email;
    private String userName;

    private String firstName;
    private String lastName;
    private String password;
    private String role;
    private String signInProvider;
    private String providerUserId;

    public MyUserAccountForm() {

    }

    public MyUserAccountForm(Connection<?> connection) {
        UserProfile socialUserProfile = connection.fetchUserProfile();
        this.id = null;
        this.email = socialUserProfile.getEmail();
        this.userName = socialUserProfile.getUsername();
        this.firstName = socialUserProfile.getFirstName();
        this.lastName = socialUserProfile.getLastName();

        ConnectionKey key = connection.getKey();
        // google, facebook, twitter
        this.signInProvider = key.getProviderId();

        // ID of User on google, facebook, twitter.
        // ID của User trên google, facebook, twitter.
        this.providerUserId = key.getProviderUserId();
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    public String getSignInProvider() {
        return signInProvider;
    }

    public void setSignInProvider(String signInProvider) {
        this.signInProvider = signInProvider;
    }

    public String getProviderUserId() {
        return providerUserId;
    }

    public void setProviderUserId(String providerUserId) {
        this.providerUserId = providerUserId;
    }

}
SecurityUtil.java
package org.o7planning.socialsecurity.util;

import org.o7planning.socialsecurity.model.MyUserAccount;
import org.o7planning.socialsecurity.user.MySocialUserDetails;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

public class SecurityUtil {

   // Auto login.
   public static void logInUser(MyUserAccount user) {

       MySocialUserDetails userDetails = new MySocialUserDetails(user);

       Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null,
               userDetails.getAuthorities());
       SecurityContextHolder.getContext().setAuthentication(authentication);
   }
 
}

8. Controller

MainController.java
package org.o7planning.socialsecurity.controller;

import org.o7planning.socialsecurity.dao.MyUserAccountDAO;
import org.o7planning.socialsecurity.form.MyUserAccountForm;
import org.o7planning.socialsecurity.model.MyUserAccount;
import org.o7planning.socialsecurity.util.SecurityUtil;
import org.o7planning.socialsecurity.validator.MyUserAccountValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.web.ProviderSignInUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
// Need to use RedirectAttributes
@EnableWebMvc
public class MainController {

   @Autowired
   private MyUserAccountDAO myUserAccountDAO;

   @Autowired
   private ConnectionFactoryLocator connectionFactoryLocator;

   @Autowired
   private UsersConnectionRepository connectionRepository;

   @Autowired
   private MyUserAccountValidator myUserAccountValidator;

   // Set a form validator
   @InitBinder
   protected void initBinder(WebDataBinder dataBinder) {
       Object target = dataBinder.getTarget();
       if (target == null) {
           return;
       }
       System.out.println("Target=" + target);

       if (target.getClass() == MyUserAccountForm.class) {
           dataBinder.setValidator(myUserAccountValidator);
       }
   }

   @RequestMapping(value = { "/" }, method = RequestMethod.GET)
   public String homePage(Model model) {
       try {
           UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication()
                   .getPrincipal();
           if (userDetails != null) {
               System.out.println(userDetails.getPassword());
               System.out.println(userDetails.getUsername());
               System.out.println(userDetails.isEnabled());

               model.addAttribute("userDetails", userDetails);
           }
       } catch (Exception e) {
       }
       return "index";
   }

   @RequestMapping(value = { "/login" }, method = RequestMethod.GET)
   public String welcomePage(Model model) {
       return "login";
   }

   // User login via Social,
   // but not allow access basic info.
   // webapp will redirect to /signin.
   @RequestMapping(value = { "/signin" }, method = RequestMethod.GET)
   public String signInPage(Model model) {
       return "redirect:/login";
   }

   @RequestMapping(value = { "/signup" }, method = RequestMethod.GET)
   public String signupPage(WebRequest request, Model model) {

       ProviderSignInUtils providerSignInUtils //
               = new ProviderSignInUtils(connectionFactoryLocator, connectionRepository);

 
       Connection<?> connection = providerSignInUtils.getConnectionFromSession(request);

       //
       MyUserAccountForm myForm = null;
       //
       if (connection != null) {
           myForm = new MyUserAccountForm(connection);
       } else {
           myForm = new MyUserAccountForm();
       }
       model.addAttribute("myForm", myForm);
       return "signup";
   }

   @RequestMapping(value = { "/signup" }, method = RequestMethod.POST)
   public String signupSave(WebRequest request, //
           Model model, //
           @ModelAttribute("myForm") @Validated MyUserAccountForm accountForm, //
           BindingResult result, //
           final RedirectAttributes redirectAttributes) {

       // If validation has error.
       if (result.hasErrors()) {
           return "signup";
       }

       MyUserAccount registered = null;

       try {
           registered = myUserAccountDAO.registerNewUserAccount(accountForm);
       } catch (Exception ex) {
           ex.printStackTrace();
           model.addAttribute("errorMessage", "Error " + ex.getMessage());
           return "signup";
       }

       if (accountForm.getSignInProvider() != null) {
           ProviderSignInUtils providerSignInUtils //
                   = new ProviderSignInUtils(connectionFactoryLocator, connectionRepository);

           // If the user is signing in by using a social provider, this method
           // call stores the connection to the UserConnection table.
           // Otherwise, this method does not do anything.
           providerSignInUtils.doPostSignUp(registered.getId(), request);
       }
       // After register, Logs the user in.
       SecurityUtil.logInUser(registered);

       return "redirect:/userInfo";
   }

   @RequestMapping(value = { "/userInfo" }, method = RequestMethod.GET)
   public String userInfoPage(WebRequest request, Model model) {
       return "userInfo";
   }

}

9. Страницы JSP

_menu.jsp
<%@ taglib uri="http://www.springframework.org/security/tags"
    prefix="security"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<div style="padding: 5px; border: 1px solid #ccc;">

    <a href="${pageContext.request.contextPath}/">Home</a>
   
        ||
   
    <a href="${pageContext.request.contextPath}/userInfo">User Info</a>

    <security:authorize access="isAuthenticated()">
        ||
        <a href="${pageContext.request.contextPath}/logout">Logout</a>

    </security:authorize>

    <security:authorize access="!isAuthenticated()">
        ||
        <a href="${pageContext.request.contextPath}/login">Login</a>

    </security:authorize>

    <c:if test="${not empty pageContext.request.userPrincipal.name}">
        ||
        <span>Welcome : ${pageContext.request.userPrincipal.name}</span>
       
                      <ul>
                    <c:forEach items="${userDetails.authorities}" var="auth">
                        <li>${auth.authority }</li>
                    </c:forEach>
                </ul>
    </c:if>
</div>
index.jsp
<%@ taglib uri="http://www.springframework.org/security/tags"
    prefix="security"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<html>
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
    <jsp:include page="_menu.jsp"/>
  
    <h2>Home Page</h2>
   
    <c:if test="${empty pageContext.request.userPrincipal.name}">
       Click to 'User Info' to show user info (It will redirect to login page)
    </c:if>
</body>
</html>
login.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta charset="UTF-8">
<title>Login Page</title>
</head>
<body>
    <jsp:include page="_menu.jsp" />


    <h2>Social Login</h2>

    <a href="${pageContext.request.contextPath}/auth/facebook">Face
        Book</a>
    <br />
    <a href="${pageContext.request.contextPath}/auth/google">Google</a>
    <br />
   
    <h2>Normal Login</h2>
     <c:if test="${param.error == 'true'}">
         <div style="color:red;margin:10px 0px;">
         
                Login Failed!!!<br />
                Reason :  ${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
                
         </div>
    </c:if>   
    <form action="${pageContext.request.contextPath}/j_spring_security_check" method='POST'>
       <table>
         <tr>
            <td>User:</td>
            <td><input type='text' name='username' value=''></td>
         </tr>
         <tr>
            <td>Password:</td>
            <td><input type='password' name='password' /></td>
         </tr>
         <tr>
            <td><input name="submit" type="submit" value="submit" /></td>
         </tr>
      </table>
    </form>

</body>
</html>
signup.jsp
<!DOCTYPE html>
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="sec"
    uri="http://www.springframework.org/security/tags"%>
<html>
<head>
<meta charset="UTF-8">
<title>Sign Up</title>
<style>
  .error-message {
    font-size:90%;
    font-style:italic;
    color:red;
  }
</style>
</head>
<body>
    <jsp:include page="_menu.jsp" />
   
    <h1>Register</h1>
   
    <c:if test="${not empty myForm.signInProvider}">
        <h2 style="color:blue;">Signup with ${myForm.signInProvider}</h2>
    </c:if>

    <form:form modelAttribute="myForm" method="POST">
        <form:hidden path="id" />
        <form:hidden path="signInProvider" />  
        <table border="0">
            <tr>
                <td>User Name</td>
                <td><form:input path="userName" /></td>
                <td><form:errors path="userName" class="error-message" /></td>
            </tr>
            <tr>
                <td>Email</td>
                <td><form:input path="email" /></td>
                <td><form:errors path="email" class="error-message" /></td>
            </tr>
            <tr>
                <td>First Name</td>
                <td><form:input path="firstName" /></td>
                <td><form:errors path="firstName" class="error-message" /></td>
            </tr>
            <tr>
                <td>Last Name</td>
                <td><form:input path="lastName" /></td>
                <td><form:errors path="lastName" class="error-message" /></td>
            </tr>
            <tr>
                <td>Password</td>
                <td><form:input path="password" /></td>
                <td><form:errors path="password" class="error-message" /></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="submit" value="Submit" /></td>
                <td></td>
            </tr>
        </table>



    </form:form>
    <div class="error-message">${errorMessage}</div>
</body>
</html>
userInfo.jsp
<%@ taglib uri="http://www.springframework.org/security/tags"
    prefix="security"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<html>
<head>
<meta charset="UTF-8">
<title>User Info</title>
</head>
<body>
    <jsp:include page="_menu.jsp" />
   
    <h1>User Info Page</h1>
    <h3>Welcome : ${pageContext.request.userPrincipal.name}</h3>
    <a href="${pageContext.request.contextPath}/logout">Logout</a>
   

</body>
</html>

10. Запуск приложения

No ADS
Примечания: Для теста приложения вы можете удалить все данные User в Database, и удалить Cache браузера:
Delete from User_Accounts;
Delete From Userconnection;
Автоматически создать аккаунт:
В случае вы хотите, чтобы при логине пользователя через социальную сеть, записи USERCONNECTION & USER_ACCOUNTS создались автоматически. Вам нужно редактировать класс SocialConfig:
** SocialConfig.java **
@Configuration
@EnableSocial
// Load to Environment.
@PropertySource("classpath:social-cfg.properties")
public class SocialConfig implements SocialConfigurer {
  
    // .....
    private boolean autoSignUp = true;

   .......
}
Отображение страницы регистрации
В случае, когда пользователь входит в систему через социальную сеть, если не соответствующей записи USERCONNECTION, приложение перенаправит к странице регистрации. Вам нужно редактировать класс SocialConfig:
** SocialConfig.java **
@Configuration
@EnableSocial
// Load to Environment.
@PropertySource("classpath:social-cfg.properties")
public class SocialConfig implements SocialConfigurer {
  
    // .....
    private boolean autoSignUp = false;

   .......
}
No ADS