Spring Boot 中如何使用 Spring Security OAuth2 来实现单点登录
简介
在现代 Web 应用程序中,单点登录(Single Sign-On,简称 SSO)是一个非常重要的功能。Spring Security OAuth2 是 Spring Security 框架的一个扩展,它提供了一种简单的方式来实现 SSO。在本文中,我们将介绍如何在 Spring Boot 应用程序中使用 Spring Security OAuth2 来实现单点登录。

准备工作
在开始之前,我们需要安装 Java 开发环境和 Maven 构建工具。此外,我们还需要一个 OAuth2 服务器,本文中我们将使用 Keycloak 作为我们的 OAuth2 服务器。
你可以从 Keycloak 官方网站下载并安装 Keycloak,并确保它正在运行。在 Keycloak 中,我们需要创建一个名为 demo 的 Realm,然后为该 Realm 创建一个名为 web 的客户端。
配置 Spring Boot 应用程序
首先,我们需要在 pom.xml 文件中添加 Spring Security OAuth2 的依赖:
<dependency>
    <groupId>org.springframework.security.oauth.boot</groupId>
    <artifactId>spring-security-oauth2-autoconfigure</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>
 
接下来,我们需要在 application.yml 或 application.properties 文件中配置 OAuth2 客户端信息,例如:
spring.security.oauth2.client.registration.keycloak.client-id=web
spring.security.oauth2.client.registration.keycloak.client-secret=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.redirect-uri={baseUrl}/login/oauth2/code/{registrationId}
spring.security.oauth2.client.registration.keycloak.scope=openid,profile,email
spring.security.oauth2.client.provider.keycloak.token-uri=http://localhost:8080/auth/realms/demo/protocol/openid-connect/token
spring.security.oauth2.client.provider.keycloak.authorization-uri=http://localhost:8080/auth/realms/demo/protocol/openid-connect/auth
spring.security.oauth2.client.provider.keycloak.user-info-uri=http://localhost:8080/auth/realms/demo/protocol/openid-connect/userinfo
spring.security.oauth2.client.provider.keycloak.jwk-set-uri=http://localhost:8080/auth/realms/demo/protocol/openid-connect/certs
spring.security.oauth2.client.provider.keycloak.user-name-attribute=sub
 
在上面的配置中,我们指定了 OAuth2 客户端的相关信息,包括客户端 ID、客户端密钥、授权类型、重定向 URI、范围和提供程序的 URI。你需要根据实际情况修改这些配置。
配置 Spring Security
要使用 Spring Security OAuth2 实现单点登录,我们需要配置 Spring Security。在 Spring Boot 应用程序中,我们可以使用 @EnableOAuth2Sso 注释来启用 Spring Security OAuth2:
@Configuration
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception { 
        http.antMatcher("/**")
            .authorizeRequests()
            .antMatchers("/", "/login**", "/error**")
            .permitAll()
            .anyRequest()
            .authenticated();
    }
}
 
在上面的代码中,我们使用 @EnableOAuth2Sso 注释启用 Spring Security OAuth2,并覆盖了 WebSecurityConfigurerAdapter 中的 configure 方法来配置 Spring Security 的 HTTP 安全。我们使用 antMatcher 方法指定要保护的 URL,使用 authorizeRequests 方法配置授权规则,使用 permitAll 方法允许所有用户访问登录页面,使用 authenticated 方法要求用户必须进行身份验证才能访问其他页面。
集成用户信息
在使用 Spring Security OAuth2 进行身份验证后,我们需要将用户的信息集成到我们的应用程序中。在 Spring Security OAuth2 中,我们可以使用 @EnableOAuth2Sso 注释中的 UserDetailsService 属性来配置用户信息服务,例如:
@Configuration
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
            .authorizeRequests()
            .antMatchers("/", "/login**", "/error**")
            .permitAll()
            .anyRequest()
            .authenticated();
    }
    @Bean
    public GrantedAuthoritiesMapper grantedAuthoritiesMapper() {
        return (authorities) -> {
            Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
            for (GrantedAuthority authority : authorities) {
                mappedAuthorities.add(new SimpleGrantedAuthority(authority.getAuthority()));
            }
            return mappedAuthorities;
        };
    }
    @Bean
    public OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
        return oidcUserRequest -> {
            OidcUserService delegate =new OidcUserService();
            OidcUser oidcUser = delegate.loadUser(oidcUserRequest);
            Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
            mappedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new DefaultOAuth2User(mappedAuthorities, oidcUser.getAttributes(), oidcUser.getNameAttributeKey());
        };
    }
}
 
在上面的代码中,我们定义了一个 oidcUserService Bean,它使用 OidcUserService 类来加载用户信息,并将用户信息映射为 DefaultOAuth2User 对象。我们还定义了一个 grantedAuthoritiesMapper Bean,它将授权映射为与 Spring Security 兼容的形式。
集成注销功能
在单点登录中,注销功能也非常重要。在 Spring Security OAuth2 中,我们可以使用 SecurityContextLogoutHandler 类来实现注销功能,例如:
@Controller
public class LogoutController {
    @GetMapping("/logout")
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        new SecurityContextLogoutHandler().logout(request, null, null);
        return "redirect:/";
    }
}
 
在上面的代码中,我们定义了一个 /logout 路径,当用户访问该路径时,我们将使用 SecurityContextLogoutHandler类来清除用户的身份验证信息,并将用户重定向到首页。
总结
在本文中,我们介绍了如何在 Spring Boot 应用程序中使用 Spring Security OAuth2 来实现单点登录。我们学习了如何配置 OAuth2 客户端信息、配置 Spring Security、集成用户信息和集成注销功能。希望这篇文章对你有所帮助!


















