• Spring Security OAuth2实现单点登录


    1、概述

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

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

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

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

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

    2、客户端应用

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

    2.1、Maven 依赖

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

    <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 注解,我们用它来启用单点登录。

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

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

    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
    

    有几点需要说明:

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

    另外需要注意,在本例中,我们使用了自己搭建的授权服务器,当然,我们也可以使用其他第三方提供商的授权服务器,例如 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 页面需要用户进行身份验证。 如果未经过身份验证的用户尝试访问 securedPage.html,他们将首先被重定向到登录页面。

    3、认证服务器

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

    3.1、Maven 依赖

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

    <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 配置

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

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

    @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 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:

    server.port=8081
    server.context-path=/auth
    security.basic.enabled=false
    

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

    @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、用户端点

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

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

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

    4、结论

    在这篇快速教程中,我们使用 Spring Security Oauth2 和 Spring Boot 实现了单点登录。

    一如既往,您可以在 GitHub 上找到完整的源码。

    原文项目示例代码

    github.com/eugenp/tuto…

    本文转载自

    原文作者:云栖路

    原文链接:https://blog.csdn.net/s573626822/article/details/79870244

  • 相关阅读:
    关于tp5框架的安装与配置
    关于php的前台,后台的基本写法
    提取大段文字中的特殊段落
    UGUI 打图集
    事件管理
    tornado install
    Install aws cli
    code migrate
    Codecommit
    Curl elasticsearch
  • 原文地址:https://www.cnblogs.com/xifengxiaoma/p/9508719.html
Copyright © 2020-2023  润新知