- 前言
- 第一部分 基础应用开发
- 第 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());
}
......
}
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论