最整洁的 Spring Security OAuth2 的 SSO 单点登录 示例

大体介绍

  • 在本教程中,我们将讨论如何使用Spring Security OAuth和Spring Boot实现SSO(单点登录)。

  • 我们将使用三个单独的应用程序:

授权服务器 - 这是中央身份验证机制
两个使用SSO的客户端程序

  • 简单来说,当用户试图访问需要认证的页面的时候,他们将被重定向到授权服务器进行身份验证,认证成功后才能访问。

我们将使用OAuth2中的授权码模式来进行身份验证。


客户端程序

我们先从客户端应用程序开始配置;我们将使用最简单的Spring Boot配置来完成。

Maven依赖

首先,我们需要在pom.xml中加入以下的依赖项:


    org.springframework.boot
    spring-boot-starter-web


    org.springframework.boot
    spring-boot-starter-security


    org.springframework.security.oauth.boot
    spring-security-oauth2-autoconfigure
    2.0.1.RELEASE

Security相关配置

下面是在客户端中关键的Security配置内容,主要继承WebSecurityConfigurerAdapter

@Configuration
@EnableOAuth2Sso
public class UiSecurityConfig extends WebSecurityConfigurerAdapter {
     
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
          .authorizeRequests()
          .antMatchers("/", "/login**")
          .permitAll()
          .anyRequest()
          .authenticated();
    }
}
  • antMatcher("/**") 表示匹配以/开头的路由
  • .authorizeRequests()表示以authorizeRequests开始进行验证
  • .antMatchers("/", "/login**").permitAll() 表示允许/(首页)和/login开头的路由通过,因为我们验证之前要允许别人访问这些页面。
  • .anyRequest().authenticated()表示其它的路由都需要经过验证

我们这个客户端程序还有一个核心的点,就是我们要加上@EnableOAuth2Sso注解,以表明是一个SSO应用配置。

接下来就是启动文件的配置:

server:
    port: 8082
security:
  basic:
    enabled: false
  oauth2:
    client:
      clientId: SampleClientId
      clientSecret: secret
      accessTokenUri: http://localhost:8081/auth/oauth/token
      userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
    resource:
      userInfoUri: http://localhost:8081/auth/user/me

我们在controller定义一个路由,访问 http://127.0.0.1:8082/admin/ 会直接访问不通。接下来,我们继续配置认证服务器,让程序可以继续。

@RestController
@RequestMapping("/admin")
@Validated
public class AdminController {
    @RequestMapping(value="/")
    public PageInfo listByPage() {
        return  "这是一个分页列表程序";
    }
}

认证服务器

接下来我们来讨论怎么配置认证服务器相关的内容。

Maven 依赖配置

首先,我们需要在pom.xml文件中加入以下的依赖:


    org.springframework.boot
    spring-boot-starter-web


    org.springframework.security.oauth
    spring-security-oauth2
    2.3.3.RELEASE

认证配置

在这里我要重点理解将授权服务器和资源服务器一起运行,作为一个应用程序来部署。

首先,我们先配置资源服务器,在启动类中,加入@EnableResourceServer注解:

@SpringBootApplication
@EnableResourceServer
public class AuthorizationServerApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(AuthorizationServerApplication.class, args);
    }
}

然后配置我们的认证服务器:

@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
     
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
 
    @Override
    public void configure(
      AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("permitAll()")
          .checkTokenAccess("isAuthenticated()");
    }
 
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
          .withClient("SampleClientId")
          .secret(passwordEncoder.encode("secret"))
          .authorizedGrantTypes("authorization_code")
          .scopes("user_info")
          .autoApprove(true) 
          .redirectUris("http://localhost:8081/login","http://localhost:8083/login"); //有多个客户端程序可以继续加
    }
}

请出注意,我们这里使用的是authorization_code授权模式。

另外,请注意autoApprove设置为true,那么我们就不会被重定向,并且可以提升为手动批准任何的scopes。

认证信息相关配置

首先,在我们的application.yml配置如下基本信息

server:
  port: 8081
  servlet:
    context-path : /auth

现在,我们配置一些登录信息。

@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
          .antMatchers("/login", "/oauth/authorize")
          .and()
          .authorizeRequests()
          .anyRequest().authenticated()
          .and()
          .formLogin().permitAll();
    }
 
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("john")
            .password(passwordEncoder().encode("123"))
            .roles("USER");
    }
     
    @Bean
    public BCryptPasswordEncoder passwordEncoder(){ 
        return new BCryptPasswordEncoder(); 
    }
}

@Order(1)代表优先执行,这里代表先执行SecurityConfig的配置,在执行AuthServerConfig的配置。
withUserpassword代表相关的认证信息,该信息可以结合实际情况在数据库等途径取出。
BCryptPasswordEncoder对密码进行加密。

认证信息

最后,我们可以建立一个路由来获取用户的认证相关的信息。

@RestController
public class UserController {
    @GetMapping("/user/me")
    public Principal user(Principal principal) {
        return principal;
    }
}

你可能感兴趣的:(最整洁的 Spring Security OAuth2 的 SSO 单点登录 示例)