- 前言
- 第一部分 基础应用开发
- 第 1 章 Spring Boot 入门
- 第 2 章 在 Spring Boot 中使用数据库
- 第 3 章 Spring Boot 界面设计
- 第 4 章 提高数据库访问性能
- 第 5 章 Spring Boot 安全设计
- 第二部分 分布式应用开发
- 第 6 章 Spring Boot SSO
- 第 7 章 使用分布式文件系统
- 第 8 章 云应用开发
- 第 9 章 构建高性能的服务平台
- 第三部分 核心技术源代码分析
- 第 10 章 Spring Boot 自动配置实现原理
- 第 11 章 Spring Boot 数据访问实现原理
- 第 12 章 微服务核心技术实现原理
- 附录 A 安装 Neo4j
- 附录 B 安装 MongoDB
- 附录 C 安装 Redis
- 附录 D 安装 RabbitMQ
- 结束语
6.2 登录认证模块
如果只是本地的登录认证,只要使用 Spring Security 就足够了。由于使用 SSO 实现了远程的登录认证功能,所以在登录认证系统中,需要增加 OAuth2 协议,让它可以支持第三方应用的认证和授权。
登录认证系统将建立一个用户中心,对使用 SSO 服务的每一个应用系统,提供统一的用户管理。而对于一个用户来说,使用任何一个应用系统,都可以通过 SSO 的 OAuth2 协议进行认证和授权确认。
6.2.1 使用 OAuth2
要使用 OAuth2,在登录认证模块和安全配置模块中都要在工程的 Maven 依赖管理中增加 OAuth2 的依赖配置,如代码清单 6-1 所示。
代码清单 6-1 OAuth2 依赖配置
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency>
6.2.2 创建数字证书
在 OAuth2 的认证服务端中,需要一个数字证书,为通信中的数字签名等功能提供支持。这个数字证书可以使用 Java 的 keystore 来生成。下面介绍这个数字证书的生成过程,在实例工程中已经具有这个证书,不用重新生成。
在 Windows 操作系统中打开一个命令行窗口,使用下列的指令可以生成一个数字证书:
C:\Users\Alan>keytool -genkey -keystore keystore.jks -alias tycoonclient -keyalg RSA
执行这个指令的操作过程如下:
输入密钥库口令 :再次输入新口令 :您的名字与姓氏是什么 ? [Unknown]: localhost 您的组织单位名称是什么 ? [Unknown]: test 您的组织名称是什么 ? [Unknown]: test 您所在的城市或区域名称是什么 ? [Unknown]: sz 您所在的省 /市 /自治区名称是什么 ? [Unknown]: gd 该单位的双字母国家 /地区代码是什么 ? [Unknown]: cn CN=localhost, OU=test, O=test, L=sz, ST=gd, C=cn 是否正确 ? [否 ]: y 输入 <tycoonclient> 的密钥口令 (如果和密钥库口令相同 , 按回车 ):
在上面操作的过程中,输入的密码是 tc123456,证书的别名设定为 tycoonclient,证书的文件保存为 keystore.jks。
然后,将生成的证书文件拷贝到登录认证模块的 resources 文件夹中,并在 OAuth2 配置中设定其相应的参数。
6.2.3 认证服务端配置
登录认证模块实现了 SSO 认证和授权服务的功能,在这里必须对 OAuth2 的认证和授权服务,以及对 Spring Security 的安全管理策略等进行一些相关的设计和配置,为使用 SSO 的客户端提供认证和授权的管理功能。
1.OAuth2 服务端配置
在登录认证模块中,编写一个 OAuthConfigurer 配置类程序,如代码清单 6-2 所示,它继承了 AuthorizationServerConfigurerAdapter。其中,使用注解 @EnableAuthoriza-tionServer 来启用 OAuth2 的认证服务器功能。在 JwtAccessTokenConverter 方法中使用上面生成的数字证书:keystore.jks,并设置了密码和别名等参数。在重载的 configure 方法中设定 OAuth2 的客户端 ID 为 ssoclient,密钥为 ssosecret,这将在使用 SSO 的客户端的配置中用到。另外,注意“autoApprove(true)”这行代码设定了自动确认授权,这样登录用户登录后,不再需要进行一次授权确认操作。
代码清单 6-2 OAuth2 服务端配置
@Configuration @EnableAuthorizationServer public class OAuthConfigurer extends AuthorizationServerConfigurerAdapter { @Bean public JwtAccessTokenConverter jwtAccessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); KeyPair keyPair = new KeyStoreKeyFactory(new ClassPathResource( "keystore.jks"), "tc123456".toCharArray()).getKeyPair("tycoon client"); converter.setKeyPair(keyPair); return converter; } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory().withClient("ssoclient").secret("ssosecret") .autoApprove(true) .authorizedGrantTypes("authorization_code", "refresh_token") .scopes("openid"); } ... }
2.Spring Security 服务端配置
因为认证服务器的 Spring Security 安全策略配置与客户端的安全策略配置不同,所以它没有使用工程中安全配置模块中的配置,而是单独使用一个配置类来实现,如代码清单 6-3 所示。这里有点像第 5 章的安全策略配置,依然提供了记住用户登录状态的功能,这样当用户选择记住登录状态登录后,只要用户不执行退出,在记住登录状态的有效期内,重新打开授权的链接时就可以不用再次登录。登录页面设定还是使用“/login”。但是这里没有针对角色的一些权限管理配置,这是因为在登录认证模块中只提供了登录认证功能,并不提供其他访问链接,所以这里不需要配置一些链接的角色权限管理。
代码清单 6-3 认证服务器的安全策略配置
@Configuration @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private CustomUserDetailsService customUserDetailsService; @Autowired @Qualifier("dataSource") private DataSource dataSource; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder()); // remember me auth.eraseCredentials(false); } @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin().loginPage("/login").permitAll().successHandler(loginSuccess Handler()) .and().authorizeRequests() .antMatchers("/images/**", "/checkcode", "/scripts/**", "/styles/ **").permitAll() .anyRequest().authenticated() .and().sessionManagement().sessionCreationPolicy(SessionCrea tionPolicy.NEVER) .and().exceptionHandling().accessDeniedPage("/deny") .and().rememberMe().tokenValiditySeconds(86400).tokenRepository (tokenRepository()); } ...... }
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论