前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Security OAuth2实现单点登录

Spring Security OAuth2实现单点登录

作者头像
朝雨忆轻尘
发布2019-06-18 19:28:07
2.1K0
发布2019-06-18 19:28:07
举报
文章被收录于专栏:朝雨忆轻尘朝雨忆轻尘

1、概述

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

本示例将使用到三个独立应用

  • 一个授权服务器(中央认证机制)
  • 两个客户端应用(使用到了 SSO 的应用)

简而言之,当用户尝试访问客户端应用的安全页面时,他们首先通过身份验证服务器重定向进行身份验证。

我们将使用 OAuth2 中的 Authorization Code 授权类型来驱动授权。

2、客户端应用

先从客户端应用下手,使用 Spring Boot 来最小化配置:

2.1、Maven 依赖

首先,需要在 pom.xml 中添加以下依赖:

代码语言:javascript
复制
<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、安全配置

接下来,最重要的部分就是客户端应用的安全配置:

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

当然,该配置的核心部分是 @EnableOAuth2Sso 注解,我们用它来启用单点登录。

请注意,我们需要继承 WebSecurityConfigurerAdapter — 如果没有它,所有路径都将被保护 — 因此用户在尝试访问任何页面时将被重定向到登录页面。 在当前这个示例中,索引页面和登录页面可以在没有身份验证的情况下可以访问。

最后,我们还定义了一个 RequestContextListener bean 来处理请求。

application.yml

代码语言:javascript
复制
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

有几点需要说明:

  • 我们禁用了默认的 Basic Authentication
  • accessTokenUri 是获取访问令牌的 URI
  • userAuthorizationUri 是用户将被重定向到的授权 URI
  • 用户端点 userInfoUri URI 用于获取当前用户的详细信息

另外需要注意,在本例中,我们使用了自己搭建的授权服务器,当然,我们也可以使用其他第三方提供商的授权服务器,例如 Facebook 或 GitHub。

2.3、前端

现在来看看客户端应用的前端配置。我们不想把太多时间花费在这里

客户端应用有一个非常简单的前端:

index.html:

代码语言:javascript
复制
<h1>Spring Security SSO</h1>
<a href="securedPage">Login</a>

securedPage.html:

代码语言:javascript
复制
<h1>Secured Page</h1>
Welcome, <span th:text="${#authentication.name}">Name</span>

securedPage.html 页面需要用户进行身份验证。 如果未经过身份验证的用户尝试访问 securedPage.html,他们将首先被重定向到登录页面。

3、认证服务器

现在让我们开始来讨论授权服务器。

3.1、Maven 依赖

首先,在 pom.xml 中定义依赖:

代码语言:javascript
复制
<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 配置

理解我们为什么要在这里将授权服务器和资源服务器作为一个单独的可部署单元一起运行这一点非常重要。

让我们从配置资源服务器开始探讨:

代码语言:javascript
复制
@SpringBootApplication
@EnableResourceServer
public class AuthorizationServerApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(AuthorizationServerApplication.class, args);
    }
}

之后,配置授权服务器:

代码语言:javascript
复制
@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 授权类型来开启一个简单的客户端。

3.3、安全配置

首先,我们将通过 application.properties 禁用默认的 Basic Authentication:

代码语言:javascript
复制
server.port=8081
server.context-path=/auth
security.basic.enabled=false

现在,让我们到配置定义一个简单的表单登录机制:

代码语言:javascript
复制
@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");
    }
}

请注意,虽然我们使用了简单的内存认证,但可以很简单地将其替换为自定义的 userDetailsService

3.4、用户端点

最后,我们将创建之前在配置中使用到的用户端点:

代码语言:javascript
复制
@RestController
public class UserController {
    @GetMapping("/user/me")
    public Principal user(Principal principal) {
        return principal;
    }
}

用户数据将以 JSON 形式返回。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-08-20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、概述
  • 2、客户端应用
    • 2.1、Maven 依赖
      • 2.2、安全配置
        • 2.3、前端
        • 3、认证服务器
          • 3.1、Maven 依赖
            • 3.2、OAuth 配置
              • 3.3、安全配置
                • 3.4、用户端点
                相关产品与服务
                多因子身份认证
                多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档