千阳县住房和城乡建设局网站,网站开发要跑道吗,工程公司起名,wordpress分享跳转插件过去#xff0c;用户使用用户名和密码组合登录。 尽管如今有些人仍然偏爱传统方式#xff0c;但越来越多的用户希望使用其社交媒体帐户登录。 这就是使Spring Social#xff08;及其子项目#xff09;成为Spring项目组合有用的补充的原因。 但是#xff0c;将Spring Soci… 过去用户使用用户名和密码组合登录。 尽管如今有些人仍然偏爱传统方式但越来越多的用户希望使用其社交媒体帐户登录。 这就是使Spring Social及其子项目成为Spring项目组合有用的补充的原因。 但是将Spring Social与Spring Security集成起来有点麻烦。 Spring Social 1.1.0改变了这一切。 它提供了与Spring Security的无缝集成并且Spring Security的Java配置支持使配置就像在公园里散步一样。 您不必相信我的话。 继续阅读您将学到如何做到这一点。 我们解决方案的要求如下 必须可以使用常规注册表单创建用户帐户。 必须有可能通过使用社交登录来创建用户帐户。 必须可以使用用户名和密码登录。 必须可以使用SaaS API提供程序进行登录。 该应用程序必须支持Facebook和Twitter。 应用程序必须使用“常规” Spring MVC控制器无REST。 让我们先看一下本教程的先决条件。 先决条件 本教程假定您已经创建了示例应用程序使用的Facebook和Twitter应用程序。 您可以通过以下链接创建这些应用程序 Facebook开发人员 Twitter开发人员 如果您不知道该怎么做可以查看以下链接 Facebook开发人员–创建应用程序详细信息页面 当系统询问您的应用程序如何与FB集成时选择“使用Facebook登录名的网站”。 如何通过8个简单步骤创建Twitter应用程序 启用“允许该应用程序用于通过Twitter登录”复选框。 让我们继续前进了解如何使用Maven获得所需的依赖关系。 使用Maven获取所需的依赖关系 我们要做的第一件事是使用Maven获得所需的依赖关系。 为此我们可以在POM文件中声明以下依赖关系 Spring Security版本3.2.0.RC1。 核心模块包含核心身份验证和访问控制组件。 Apache HttpClient版本4.2.5。 Apache HttpClient是Spring Social的可选依赖项但建议使用。 如果存在Spring Social会将其用作HTTP客户端。 否则Spring social将使用标准的Java SE组件。 Spring社交版本1.1.0.BUILD-SNAPSHOT。 核心模块包含连接框架并为OAuth客户端提供支持。 Spring Social Facebook版本1.1.0.BUILD-SNAPSHOT是Spring Social的扩展它提供Facebook集成。 Spring Social Twitter版本1.1.0.BUILD-SNAPSHOT是对Social Social的扩展它提供了Twitter集成。 pom.xml文件的相关部分如下所示 !-- Spring Security --
dependencygroupIdorg.springframework.security/groupIdartifactIdspring-security-core/artifactIdversion3.2.0.RC1/version
/dependency
dependencygroupIdorg.springframework.security/groupIdartifactIdspring-security-config/artifactIdversion3.2.0.RC1/version
/dependency
dependencygroupIdorg.springframework.security/groupIdartifactIdspring-security-taglibs/artifactIdversion3.2.0.RC1/version
/dependency
dependencygroupIdorg.springframework.security/groupIdartifactIdspring-security-web/artifactIdversion3.2.0.RC1/version
/dependency!-- Use Apache HttpClient as HTTP Client --
dependencygroupIdorg.apache.httpcomponents/groupIdartifactIdhttpclient/artifactIdversion4.2.5/version
/dependency!-- Spring Social --
dependencygroupIdorg.springframework.social/groupIdartifactIdspring-social-core/artifactIdversion1.1.0.BUILD-SNAPSHOT/version
/dependency
dependency groupIdorg.springframework.social/groupIdartifactIdspring-social-security/artifactIdversion1.1.0.BUILD-SNAPSHOT/version
/dependency
dependencygroupIdorg.springframework.social/groupIdartifactIdspring-social-web/artifactIdversion1.1.0.BUILD-SNAPSHOT/version
/dependency!-- Spring Social Facebook --
dependencygroupIdorg.springframework.social/groupIdartifactIdspring-social-facebook/artifactIdversion1.1.0.BUILD-SNAPSHOT/version
/dependency!-- Spring Social Twitter --
dependencygroupIdorg.springframework.social/groupIdartifactIdspring-social-twitter/artifactIdversion1.1.0.BUILD-SNAPSHOT/version
/dependency 注意 我们的应用程序还具有其他依赖项。 例如它使用Spring Framework 3.2.4.RELEASESpring Data JPA 1.3.4和Hibernate 4.2.4.Final。 为了清楚起见这些依赖项从依赖项列表中省略。 您可以从Github获取依赖项的完整列表 。 您可能还想阅读以下文档这些文档为您提供了有关此博客文章Spring Security和Spring Social中讨论的框架的依赖性的更多信息 Spring Security参考手册1.4获取Spring Security Spring社会参考手册1.3如何获得 Spring Social Facebook参考手册1.2如何获取 Spring Social Twitter参考手册1.2如何获取 接下来我们必须为应用程序的配置属性创建一个属性文件。 让我们找出这是如何完成的。 创建属性文件 我们可以按照以下步骤创建属性文件 创建一个名为application.properties的文件并确保从类路径中找到它。 配置数据库连接。 配置休眠。 将Facebook应用程序ID和应用程序密钥添加到属性文件。 将Twitter使用者密钥和使用者密钥添加到属性文件中。 application.properties文件的内容如下所示 #Database Configuration
db.drivercom.mysql.jdbc.Driver
db.urljdbc:mysql://localhost:3306/socialtwitter
db.usernamesocialtwitter
db.passwordpassword#Hibernate Configuration
hibernate.dialectorg.hibernate.dialect.MySQL5InnoDBDialect
hibernate.format_sqltrue
hibernate.hbm2ddl.autovalidate
hibernate.ejb.naming_strategyorg.hibernate.cfg.ImprovedNamingStrategy
hibernate.show_sqlfalse#Facebook
facebook.app.idfoo
facebook.app.secretbar#Twitter
twitter.consumer.keyfoo
twitter.consumer.secretbar 在配置应用程序之前我们必须创建一些通用组件。 让我们找出这些组件是什么以及如何创建它们。 创建通用组件 我们必须创建在身份验证过程中使用的三个组件。 这些组件是 我们创建了一个类其中包含经过身份验证的用户的用户详细信息。 我们必须创建一个实现UserDetailsService接口的类。 当用户使用表单登录时此类用于加载用户信息。 我们必须创建一个实现SocialUserDetailsService接口的类。 当用户使用社交登录时该类用于加载用户信息。 让我们继续前进找出如何实现这些类。 创建用户详细信息类 在创建包含已认证用户的用户详细信息的类时我们必须考虑以下要求 存储使用表单登录的用户的用户详细信息的类必须实现UserDetails接口。 存储使用社交登录的用户的用户详细信息的类必须实现SocialUserDetails接口。 Spring Social具有满足这两个要求的SocialUser类。 但是通常我们希望将特定于应用程序的信息添加到我们的用户详细信息类中。 我们可以按照以下步骤进行操作 创建用户详细信息类。 扩展SocialUser类。 将应用程序特定的字段添加到创建的类。 我们的示例应用程序的特定于应用程序的字段是 id firstName lastName role和socialSignInProvider 。 创建一个构造函数该构造函数将用户名密码和授予的权限的集合作为参数。 将这些参数传递给SocialUser类的构造函数。 为特定于应用程序的字段创建吸气剂。 添加一个内部构建器类该类用于构建新的ExampleUserDetails对象。 我们的用户详细信息类的源代码如下所示 import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.social.security.SocialUser;import java.util.Collection;
import java.util.HashSet;
import java.util.Set;public class ExampleUserDetails extends SocialUser {private Long id;private String firstName;private String lastName;private Role role;private SocialMediaService socialSignInProvider;public ExampleUserDetails(String username, String password, Collection? extends GrantedAuthority authorities) {super(username, password, authorities);}//Getters are omitted for the sake of clarity.public static class Builder {private Long id;private String username;private String firstName;private String lastName;private String password;private Role role;private SocialMediaService socialSignInProvider;private SetGrantedAuthority authorities;public Builder() {this.authorities new HashSet();}public Builder firstName(String firstName) {this.firstName firstName;return this;}public Builder id(Long id) {this.id id;return this;}public Builder lastName(String lastName) {this.lastName lastName;return this;}public Builder password(String password) {if (password null) {password SocialUser;}this.password password;return this;}public Builder role(Role role) {this.role role;SimpleGrantedAuthority authority new SimpleGrantedAuthority(role.toString());this.authorities.add(authority);return this;}public Builder socialSignInProvider(SocialMediaService socialSignInProvider) {this.socialSignInProvider socialSignInProvider;return this;}public Builder username(String username) {this.username username;return this;}public ExampleUserDetails build() {ExampleUserDetails user new ExampleUserDetails(username, password, authorities);user.id id;user.firstName firstName;user.lastName lastName;user.role role;user.socialSignInProvider socialSignInProvider;return user;}}
} 角色是一个简单的枚举它指定示例应用程序的“合法”用户角色。 其源代码如下 public enum Role {ROLE_USER
} SocialMediaService是一个枚举用于标识用户为我们的示例应用程序创建用户帐户时使用的SaaS API提供程序。 其源代码如下 public enum SocialMediaService {FACEBOOK,TWITTER
} 实现UserDetailsService接口 通过执行以下步骤我们可以创建自己的UserDetailsService接口实现 创建一个实现UserDetailsService接口的类。 将UserRepository字段添加到创建的类。 创建一个将UserRepository作为构造函数参数的构造函数并使用Autowired注释对构造函数进行注释。 实现UserDetailsService接口的loadUserByUsernameString username方法。 此方法的实现包括以下步骤 通过调用UserRepository接口的findByEmail方法来获取用户。 此方法返回其电子邮件与作为方法参数给出的用户名匹配的用户。 如果找不到用户则抛出新的UsernameNotFoundException 。 创建一个新的ExampleUserDetails对象。 返回创建的对象。 RepositoryUserDetailsService类的源代码如下所示 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;public class RepositoryUserDetailsService implements UserDetailsService {private UserRepository repository;Autowiredpublic RepositoryUserDetailsService(UserRepository repository) {this.repository repository;}Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user repository.findByEmail(username);if (user null) {throw new UsernameNotFoundException(No user found with username: username);}ExampleUserDetails principal ExampleUserDetails.getBuilder().firstName(user.getFirstName()).id(user.getId()).lastName(user.getLastName()).password(user.getPassword()).role(user.getRole()).socialSignInProvider(user.getSignInProvider()).username(user.getEmail()).build();return principal;}
} UserRepository是一个简单的Spring Data JPA存储库其源代码如下所示 import org.springframework.data.jpa.repository.JpaRepository;public interface UserRepository extends JpaRepositoryUser, Long {public User findByEmail(String email);
} 该用户是我们的示例应用程序的唯一实体它包含为我们的示例应用程序创建了用户帐户的用户的信息。 其源代码的相关部分如下所示 import javax.persistence.*;Entity
Table(name users)
public class User extends BaseEntityLong {IdGeneratedValue(strategy GenerationType.AUTO)private Long id;Column(name email, length 100, nullable false, unique true)private String email;Column(name first_name, length 100,nullable false)private String firstName;Column(name last_name, length 100, nullable false)private String lastName;Column(name password, length 255)private String password;Enumerated(EnumType.STRING)Column(name role, length 20, nullable false)private Role role;Enumerated(EnumType.STRING)Column(name sign_in_provider, length 20)private SocialMediaService signInProvider;public User() {}//Getters and other methods are omitted for the sake of clarity.
} 实现SocialUserDetailsService接口 我们可以通过执行以下步骤来实现SocialUserDetailsService接口 创建一个实现SocialUserDetailsService的类。 将UserDetailsService字段添加到创建的类。 创建一个将UserDetailsService对象作为构造函数参数的构造函数并使用Autowired注释对构造函数进行注释。 实现SocialUserDetailsInterface的loadUserByUserIdString userId方法。 通过调用loadUserByUsername方法获取正确的UserDetails对象并将用户ID作为方法参数传递。 我们可以这样做是因为我们的应用程序使用用户的用户名作为用户ID。 将返回的对象强制转换为SocialUserDetails对象并返回。 SimpleSocialUserDetailsService类的源代码如下所示 import org.springframework.dao.DataAccessException;
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.SocialUser;
import org.springframework.social.security.SocialUserDetails;
import org.springframework.social.security.SocialUserDetailsService;public class SimpleSocialUserDetailsService implements SocialUserDetailsService {private UserDetailsService userDetailsService;public SimpleSocialUserDetailsService(UserDetailsService userDetailsService) {this.userDetailsService userDetailsService;}Overridepublic SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException, DataAccessException {UserDetails userDetails userDetailsService.loadUserByUsername(userId);return (SocialUserDetails) userDetails;}
} 就这些。 现在我们准备配置应用程序的应用程序上下文。 让我们找出如何做到这一点。 配置应用程序上下文 本节介绍如何使用Java配置来配置示例应用程序的应用程序上下文。 遵循以下准则将应用程序上下文配置分为多个配置类 每个配置类都包含与示例应用程序的特定部分相关联的配置。 如果我们必须在创建初始配置后的几个月或几年内检出某项内容或进行某些更改则可以轻松找到相关的配置。 对配置进行了划分使之可以通过使用Spring Test MVC轻松编写Web层的单元测试。 我们将在本教程的第三部分中进一步讨论这一点在该部分中我们将为应用程序的Web层编写单元测试。 当我们为应用程序编写集成测试时使用该配置可以轻松删除对外部资源的依赖。 我们将在本教程的第四部分中进一步讨论这一点该教程描述了如何为应用程序编写集成测试。 注意 如果要使用XML配置可以查看此博客文章的示例应用程序该示例应用程序也具有有效的XML配置 尽管没有web.xml。 让我们从配置应用程序的持久层开始。 配置持久层 我们应用程序的持久层存储用户帐户信息并提供一种访问此信息的方法。 这很重要原因有两个 我们可以提供一种使用用户名和密码登录的方法。 我们可以存储特定于应用程序的信息并将此信息链接到使用社交登录的用户。 让我们找出如何通过使用两个Java配置类来配置它。 注意 示例应用程序的持久层使用Spring Data JPA 1.3.4。 我将使该部分尽可能的薄。 如果您想了解有关Spring Data JPA的更多信息可以阅读我的Spring Data JPA教程 。 我还写了一本关于Spring Data的书它应该可以帮助您立即开始使用。 我们可以按照以下步骤配置持久层 创建配置类并使用Configuration注释对创建的类进行注释。 用EnableJpaRepositories批注为类注解并设置Spring Data JPA信息库的基本包。 通过使用EnableTransactionManagement批注注释配置类来启用Spring事务管理。 在类中添加一个Environment字段并使用Autowired批注对该字段进行批注。 我们不需要使用PropertySource批注来配置属性文件因为已经在“父”应用程序上下文配置类中对其进行了配置。 配置数据源bean。 这个bean提供了到实体管理器的数据库连接但是它还有另一个目的。 当Spring Social保持与数据库的连接并从数据库加载它们的连接时将使用它。 配置事务管理器bean。 配置实体管理器工厂bean。 PersistenceContext类的源代码如下所示 import com.jolbox.bonecp.BoneCPDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Properties;Configuration
EnableJpaRepositories(basePackages {net.petrikainulainen.spring.social.signinmvc.user.repository
})
EnableTransactionManagement
public class PersistenceContext {Resourceprivate Environment env;Beanpublic DataSource dataSource() {BoneCPDataSource dataSource new BoneCPDataSource();dataSource.setDriverClass(env.getRequiredProperty(db.driver));dataSource.setJdbcUrl(env.getRequiredProperty(db.url));dataSource.setUsername(env.getRequiredProperty(db.username));dataSource.setPassword(env.getRequiredProperty(db.password));return dataSource;}Beanpublic JpaTransactionManager transactionManager() {JpaTransactionManager transactionManager new JpaTransactionManager();transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());return transactionManager;}Beanpublic LocalContainerEntityManagerFactoryBean entityManagerFactory() {LocalContainerEntityManagerFactoryBean entityManagerFactoryBean new LocalContainerEntityManagerFactoryBean();entityManagerFactoryBean.setDataSource(dataSource());entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());entityManagerFactoryBean.setPackagesToScan({net.petrikainulainen.spring.social.signinmvc.common.model,net.petrikainulainen.spring.social.signinmvc.user.model});Properties jpaProperties new Properties();jpaProperties.put(hibernate.dialect, env.getRequiredProperty(hibernate.dialect));jpaProperties.put(hibernate.format_sql, env.getRequiredProperty(hibernate.format_sql));jpaProperties.put(hibernate.hbm2ddl.auto, env.getRequiredProperty(hibernate.hbm2ddl.auto));jpaProperties.put(hibernate.ejb.naming_strategy, env.getRequiredProperty(hibernate.ejb.naming_strategy));jpaProperties.put(hibernate.show_sql, env.getRequiredProperty(hibernate.show_sql));entityManagerFactoryBean.setJpaProperties(jpaProperties);return entityManagerFactoryBean;}
} 让我们继续研究如何为应用程序创建安全配置。 配置Spring Security Spring Security为使用表单登录或社交登录的用户提供身份验证机制并且还负责授权。 我们可以按照以下步骤配置Spring Security 创建配置类并使用Configuration注释对创建的类进行注释。 用EnableWebSecurity注释对类进行注释。 这样就可以通过实现WebSecurityConfigurer接口来配置Spring Security。 确保我们的配置类扩展了WebSecurityConfigurerAdapter类该类是用于创建WebSecurityConfigurer实例的基类。 完成此操作后我们可以通过覆盖方法来自定义安全配置。 将ApplicationContext字段添加到配置类并使用Autowired批注对该字段进行批注。 将UserRepository字段添加到配置中并使用Autowired注释对该字段进行注释。 重写WebSecurityConfigurerAdapter类的configureWebSecurity web方法。 确保Spring Security忽略对静态资源例如CSS和Javascript文件的请求。 重写WebSecurityConfigurerAdapter类的configureHttpSecurity http方法并通过以下步骤实现它 通过执行以下步骤配置表单登录 将登录页面网址设置为“ / login”。 将处理登录表单提交的URL设置为“ / login / authenticate”。 将登录失败网址设置为“ / loginerror bad_credentials”。 通过执行以下步骤配置注销功能 确保注销后删除名为JSESSIONID的cookie。 将注销网址设置为“ / logout”。 将注销成功URL设置为“ / login”。 配置基于url的授权。 此阶段的主要目的是确保匿名用户可以访问与登录/注册过程相关的所有URL并保护应用程序的其余部分不受匿名用户的攻击。 将SocialAuthenticationFilter添加到Spring Security过滤器链。 为此我们可以创建一个新的SpringSocialConfigurer对象并确保在配置Spring Security时使用该对象。 将ApplicationContext字段的值设置为所有SecurityConfigurer实例共享的对象。 配置用来对用户密码进行哈希处理的PasswordEncoder bean如果用户使用表单注册和登录。 我们可以通过创建一个新的BCryptPasswordEncoder对象并返回创建的对象来做到这一点。 配置UserDetailsService Bean。 我们可以通过创建一个新的RepositoryUserDetailsService对象并将UserRepository作为构造函数参数来实现。 重写WebSecurityConfigurerAdapter类的registerAuthenticationAuthenticationManagerBuilder auth方法。 如果用户使用表单登录我们将使用此方法配置身份验证请求。 通过执行以下步骤来实现此方法 将UserDetailsService bean传递给作为方法参数给出的AuthenticationManagerBuilder对象。 将PasswordEncoder bean传递给作为方法参数给出的AuthenticationManagerBuilder对象。 配置SocialUserDetailsService bean。 我们可以通过创建一个新的SimpleSocialUserDetailsService对象并将UserDetailsService bean作为构造函数参数来实现。 使用社交登录时此bean加载用户特定的数据。 我们的应用程序上下文配置类的源代码如下所示 import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
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.builders.WebSecurity;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.social.security.SocialUserDetailsService;
import org.springframework.social.security.SpringSocialConfigurer;Configuration
EnableWebSecurity
public class SecurityContext extends WebSecurityConfigurerAdapter {Autowiredprivate ApplicationContext context;Autowiredprivate UserRepository userRepository;Overridepublic void configure(WebSecurity web) throws Exception {web//Spring Security ignores request to static resources such as CSS or JS files..ignoring().antMatchers(/static/**);}Overrideprotected void configure(HttpSecurity http) throws Exception {http//Configures form login.formLogin().loginPage(/login).loginProcessingUrl(/login/authenticate).failureUrl(/login?errorbad_credentials)//Configures the logout function.and().logout().deleteCookies(JSESSIONID).logoutUrl(/logout).logoutSuccessUrl(/login)//Configures url based authorization.and().authorizeRequests()//Anyone can access the urls.antMatchers(/auth/**,/login,/signin/**,/signup/**,/user/register/**).permitAll()//The rest of the our application is protected..antMatchers(/**).hasRole(USER)//Adds the SocialAuthenticationFilter to Spring Securitys filter chain..and().apply(new SpringSocialConfigurer()).and().setSharedObject(ApplicationContext.class, context);}Overrideprotected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());}Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(10);}Beanpublic SocialUserDetailsService socialUserDetailsService() {return new SimpleSocialUserDetailsService(userDetailsService());}Beanpublic UserDetailsService userDetailsService() {return new RepositoryUserDetailsService(userRepository);}
} 让我们继续前进了解如何配置Spring Social。 配置Spring Social Spring Social提供与Facebook和Twitter等SaaS API提供程序的集成。 我们可以按照以下步骤配置Spring Social 创建实现SocialConfigurer接口的应用程序上下文配置类并使用Configuration注释对创建的类进行注释。 SocialConfigurer接口声明了可用于配置Spring Social的回调方法。 用EnableSocial批注对类进行批注。 这将启用Spring Social并导入SocialConfiguration配置类。 用Profile注释为类添加注释并将字符串“ application”设置为其值。 这样可以确保仅在活动Spring概要文件为“ application”时使用此应用程序上下文配置类。 这很重要因为它使我们无需依赖Facebook或Twitter即可为我们的应用程序编写集成测试。 将DataSource字段添加到配置类并使用Autowired批注对该字段进行批注。 将SocialConfigurer界面的addConnectionFactories方法添加到创建的配置类中。 此方法采用以下两个方法参数 第一个参数是ConnectionFactoryConfigurer对象可用于注册连接工厂。 第二个参数是一个Environment对象它代表示例应用程序在其中运行的环境。 通过执行以下步骤来实现addConnectionFactories方法 创建一个新的TwitterConnectionFactory对象并将使用者密钥和使用者密钥作为构造函数参数传递。 通过调用ConnectionFactoryConfigurer接口的addConnectionFactory方法来注册创建的TwitterConnectionFactory对象。 将创建的TwitterConnectionFactory对象作为方法参数传递。 创建一个新的FacebookConnectionFactory对象并将应用程序ID和应用程序密钥作为构造函数参数传递。 通过调用ConnectionFactoryConfigurer接口的addConnectionFactory方法来注册创建的FacebookConnectionFactory对象。 将创建的FacebookConnectionFactory对象作为方法参数传递。 将SocialConfigurer接口的getUserIdSource方法添加到创建的类中。 此方法返回的UserIdSource对象负责确定用户的正确帐户ID。 因为我们的示例应用程序使用用户的用户名作为帐户ID所以我们必须通过返回新的AuthenticationNameUserIdSource对象来实现此方法。 将SocialConfigurer接口的getUsersConnectionRepository方法添加到创建的类中。 此方法将ConnectionFactoryLocator对象作为方法参数并返回UsersConnectionRepository对象。 通过执行以下步骤来实现getUsersConnectionRepository方法 创建一个新的JdbcUsersConnectionRepository对象并将以下对象作为构造函数参数传递 第一个参数是DataSource对象。 我们将dataSource字段的值作为第一个方法参数传递。 第二个参数是ConnectionFactoryLocator对象。 我们将connectionFactoryLocator方法参数的值作为第二个方法参数传递。 第三个参数是TextEncryptor对象该对象加密SaaS API提供程序与我们的应用程序之间建立的连接的授权详细信息。 我们通过调用Encryptors类的noOpText方法来创建此对象。 这意味着我们的示例应用程序将这些详细信息存储为纯文本。 这在开发阶段很方便但是我们不应该在生产中使用它 。 返回创建的对象。 配置ConnectController bean。 配置此bean的方法有两个参数。 第一个参数是ConnectionFactoryLocator bean。 第二个参数是使用的ConnectionRepository bean。 在创建新的ConnectController对象时将这些参数作为构造函数参数传递。 我们的配置类的源代码如下所示 import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
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.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.security.AuthenticationNameUserIdSource;
import org.springframework.social.twitter.connect.TwitterConnectionFactory;import javax.sql.DataSource;Configuration
EnableSocial
Profile(application)
public class SocialContext implements SocialConfigurer {Autowiredprivate DataSource dataSource;Overridepublic void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {cfConfig.addConnectionFactory(new TwitterConnectionFactory(env.getProperty(twitter.consumer.key),env.getProperty(twitter.consumer.secret)));cfConfig.addConnectionFactory(new FacebookConnectionFactory(env.getProperty(facebook.app.id),env.getProperty(facebook.app.secret)));}Overridepublic UserIdSource getUserIdSource() {return new AuthenticationNameUserIdSource();}Overridepublic UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {return new JdbcUsersConnectionRepository(dataSource,connectionFactoryLocator,Encryptors.noOpText());}Beanpublic ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator, ConnectionRepository connectionRepository) {return new ConnectController(connectionFactoryLocator, connectionRepository);}
} 下一步是配置应用程序的Web层。 让我们开始工作。 配置Web层 我们可以按照以下步骤配置应用程序的Web层 通过执行以下步骤来创建配置类 扩展WebMvcConfigurerAdapter类。 用Configuration注释对创建的类进行注释。 通过使用ComponentScan批注注释该类并设置控制器的基本软件包确保找到所有控制器类。 通过使用EnableWebMvc注释对类进行注释来启用注释驱动的Web mvc。 确保容器的默认Servlet提供静态资源。 通过重写WebMvcConfigurerAdapter类的addResourceHandlers方法来配置静态资源。 确保对静态资源的请求被转发到容器的默认Servlet。 这是通过重写WebMvcConfigurerAdapter类的configureDefaultServletHandling方法来完成的。 配置异常解析器 bean。 配置ViewResolver bean。 WebAppContext类的源代码如下所示 import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
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;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;import java.util.Properties;Configuration
ComponentScan(basePackages {net.petrikainulainen.spring.social.signinmvc.common.controller,net.petrikainulainen.spring.social.signinmvc.security.controller,net.petrikainulainen.spring.social.signinmvc.user.controller
})
EnableWebMvc
public class WebAppContext extends WebMvcConfigurerAdapter {Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler(/static/**).addResourceLocations(/static/);}Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}Beanpublic SimpleMappingExceptionResolver exceptionResolver() {SimpleMappingExceptionResolver exceptionResolver new SimpleMappingExceptionResolver();Properties exceptionMappings new Properties();exceptionMappings.put(java.lang.Exception, error/error);exceptionMappings.put(java.lang.RuntimeException, error/error);exceptionResolver.setExceptionMappings(exceptionMappings);Properties statusCodes new Properties();statusCodes.put(error/404, 404);statusCodes.put(error/error, 500);exceptionResolver.setStatusCodes(statusCodes);return exceptionResolver;}Beanpublic ViewResolver viewResolver() {InternalResourceViewResolver viewResolver new InternalResourceViewResolver();viewResolver.setViewClass(JstlView.class);viewResolver.setPrefix(/WEB-INF/jsp/);viewResolver.setSuffix(.jsp);return viewResolver;}
} 让我们找出如何将所有这些结合在一起并为我们的应用程序创建一个“父”应用程序上下文配置类。 绑在一起 最后一个应用程序上下文配置类具有三个职责 它配置了整个示例应用程序中使用的常规组件。 它确保在类路径扫描期间找到我们应用程序的服务类。 它是我们应用程序的根应用程序上下文配置类。 我们可以按照以下步骤创建此配置类 创建配置类并使用Configuration注释对创建的类进行注释。 通过使用ComponentScan批注注释该类并设置我们的服务的基本包确保在组件扫描期间找到我们的服务类。 通过使用Import批注对类进行导入以导入其他应用程序上下文配置类。 用PropertySource注释对类进行注释并将其配置为从类路径中查找名为application.properties的属性文件。 这样可以确保可以在导入的应用程序上下文配置类中访问配置属性。 配置MessageSource bean。 配置PropertyPlaceHolderConfigurer bean。 ExampleApplicationContext类的源代码如下所示 import org.springframework.context.MessageSource;
import org.springframework.context.annotation.*;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.context.support.ResourceBundleMessageSource;Configuration
ComponentScan(basePackages {net.petrikainulainen.spring.social.signinmvc.user.service
})
Import({WebAppContext.class, PersistenceContext.class, SecurityContext.class, SocialContext.class})
PropertySource(classpath:application.properties)
public class ExampleApplicationContext {Beanpublic MessageSource messageSource() {ResourceBundleMessageSource messageSource new ResourceBundleMessageSource();messageSource.setBasename(i18n/messages);messageSource.setUseCodeAsDefaultMessage(true);return messageSource;}Beanpublic PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {return new PropertySourcesPlaceholderConfigurer();}
} 现在我们已经配置了示例应用程序的应用程序上下文。 但是我们仍然必须配置Web应用程序。 让我们看看如何使用Java配置来做到这一点。 配置Web应用程序 我们的最后一步是配置示例应用程序。 只要将应用程序部署到Servlet 3.0兼容容器中我们就可以在没有web.xml的情况下执行此操作。 我们可以按照以下步骤配置Web应用程序 创建一个实现WebApplicationInitializer接口的类。 通过覆盖WebApplicationInitializer接口的onStartup方法来配置我们的应用程序。 我们可以通过执行以下步骤来实现此方法 创建应用程序的根上下文并将ExampleApplicationContext类注册到创建的根上下文。 配置调度程序servlet 。 C配置字符编码过滤器 。 D配置Spring Security过滤器链 。 E配置Sitemesh 。 F将上下文加载器侦听器添加到Servlet上下文。 ExampleApplicationConfig类的源代码如下所示 import org.sitemesh.config.ConfigurableSiteMeshFilter;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.DispatcherServlet;import javax.servlet.*;
import java.util.EnumSet;public class ExampleApplicationConfig implements WebApplicationInitializer {Overridepublic void onStartup(ServletContext servletContext) throws ServletException {AnnotationConfigWebApplicationContext rootContext new AnnotationConfigWebApplicationContext();rootContext.register(ExampleApplicationContext.class);ServletRegistration.Dynamic dispatcher servletContext.addServlet(dispatcher, new DispatcherServlet(rootContext));dispatcher.setLoadOnStartup(1);dispatcher.addMapping(/);EnumSetDispatcherType dispatcherTypes EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);CharacterEncodingFilter characterEncodingFilter new CharacterEncodingFilter();characterEncodingFilter.setEncoding(UTF-8);characterEncodingFilter.setForceEncoding(true);FilterRegistration.Dynamic characterEncoding servletContext.addFilter(characterEncoding, characterEncodingFilter);characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, /*);FilterRegistration.Dynamic security servletContext.addFilter(springSecurityFilterChain, new DelegatingFilterProxy());security.addMappingForUrlPatterns(dispatcherTypes, true, /*);FilterRegistration.Dynamic sitemesh servletContext.addFilter(sitemesh, new ConfigurableSiteMeshFilter());sitemesh.addMappingForUrlPatterns(dispatcherTypes, true, *.jsp);servletContext.addListener(new ContextLoaderListener(rootContext));}
}下一步是什么 现在我们已经使用Java配置成功配置了示例应用程序。 本教程教了我们两件事 我们学习了如何实现Spring Security和Spring Social所需的组件。 我们学习了通过使用Java配置来集成Spring Security和Spring Social。 本教程的下一部分描述了如何向示例应用程序添加注册和身份验证功能。 PS与往常一样此博客文章的示例应用程序可在Github上获得 。 参考 在Spring MVC Web应用程序中添加社交登录来自Petri Kainulainen博客的JCG合作伙伴 Petri Kainulainen进行的配置 。 翻译自: https://www.javacodegeeks.com/2013/10/adding-social-sign-in-to-a-spring-mvc-web-application-configuration.html