基于Spring Security OAuth2.0实现单点登录SSO

  1. 1. 概述
  2. 2. 客户端APP
    1. 2.1 Maven依赖
    2. 2.2 安全配置
    3. 2.3 前端
  3. 3. 认证服务器
    1. 3.1 Maven依赖
    2. 3.2 OAuth配置
    3. 3.3 安全配置
    4. 3.4 用户终端
  4. 参考资料:

1. 概述

本文简要总结一下如果使用Spring Security OAuth和Spring Boot来实现SSO,文末有样例代码。不了解OAuth2.0协议的同学请参考《OAuth2.0协议原理详解》

整个工程包括三个独立的应用,一个认证服务和两个客户端应用,结构非常简单。当一个用户访问客户端应用中被防护的API时,系统会被自动重定向到认证服务,之后我们使用OAuth2.0的Authorization code授权方式来实现认证授权。

2. 客户端APP

我们先从客户端应用入手,使用Spring Boot可以最大程度简化配置

2.1 Maven依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.security.oauth</groupId>
   <artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
   <groupId>org.thymeleaf.extras</groupId>
   <artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>

2.2 安全配置

客户端的安全配置如下:

@Configuration
@EnableOAuth2Sso
public class UiSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
          .authorizeRequests()
          .antMatchers("/", "/login**")
          .permitAll()
          .anyRequest()
          .authenticated();
    }
}

配置最核心的部分是 @EnableOAuth2Sso注解来开启SSO。这里要注意,我们需要重写WebSecurityConfigurerAdapter 否则所有的路径都会受到SSO的保护,这样无论用户访问哪个页面都会被重定向到登录页面,在这个例子里,index和login页面是唯一不需要被防护的。

最后,我们定义一个RequestContextListener bean来处理request scopes。

application.yml:
server:
    port: 8082
    context-path: /ui
    session:
      cookie:
        name: UISESSION
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
spring:
  thymeleaf:
    cache: false

说明:

  • 我们禁用了default Basic Authentication

  • accessTokenUri 是获取访问令牌的URL

  • userAuthorizationUri是授权用户被重定向的目标URL

  • userInfoUri是用户终端访问用户信息的URL

在这个case里,认证服务是我们自己建设的,但是在实际的应用场景下认证服务往往是第三方提供的比如Facebook 或者 gitHub

2.3 前端

前端并非本文的重点,这里简单提一下。客户端有一个非常简单的前端页面
index.html:

<h1>Spring Security SSO</h1>

<a href="securedPage">Login</a>

securedPage.html:

<h1>Secured   Page</h1>

Welcome, <span th:text="${#authentication.name}">Name</span>

securedPage.html需要用户通过授权才能访问,如果一个未授权的用户访问这个页面,他会被重定向到login页面

3. 认证服务器

3.1 Maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
</dependency>

3.2 OAuth配置

本例中我们把AS(认证服务)器和RS放(资源服务器)在一个实例中部署。

RS配置如下:

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

AS配置如下:

@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private AuthenticationManager authenticationManager;

    @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("secret")
          .authorizedGrantTypes("authorization_code")
          .scopes("user_info")
          .autoApprove(true) ; 
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }
}

这里我们只开启authorization_code授权模式,另外这里注意到autoApprove=true,这意味着用户不会被重定向到授权的页面,也不需要手动给请求授权。

3.3 安全配置

这里需要定义一个简单的认证机制

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private AuthenticationManager authenticationManager;

    @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.parentAuthenticationManager(authenticationManager)
          .inMemoryAuthentication()
          .withUser("john").password("123").roles("USER");
    }
}

注意,我们用了in-memory认证,这里只是做一个简单的例子,我们直接把账号密码写到内存里了,真正使用的时候这里要换成自定义的userDetailsService.

3.4 用户终端

一个很简单的返回JSON消息的接口

@RestController

public class UserController {

    @GetMapping("/user/me")

    public Principal user(Principal principal) {
        return principal;
    }

}

完整的代码下载链接:Over On Github

参考资料:

http://blog.csdn.net/j754379117/article/details/70175198
http://www.baeldung.com/sso-spring-security-oauth2


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 370716264@qq.com

文章标题:基于Spring Security OAuth2.0实现单点登录SSO

文章字数:1.1k

本文作者:Charles Liu

发布时间:2017-11-16, 22:25:00

最后更新:2019-12-21, 14:33:08

原始链接:http://www.dearcharles.cn/2017/11/16/基于Spring-Security-OAuth2-0实现单点登录SSO/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录