返回介绍

6.2 登录认证模块

发布于 2025-04-26 13:26:34 字数 4517 浏览 0 评论 0 收藏

如果只是本地的登录认证,只要使用 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());
    }
    ......
}

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。