单点登录,基于OAuth2.0实现 (一)

942 阅读3分钟

一、各服务讲解

1. 认证中心(Authorization Server)

  • 角色:认证中心是 OAuth 2.0 的核心,负责验证用户身份并颁发访问令牌(Access Token)。

  • 功能

    • 提供登录页面,用户输入用户名和密码进行身份验证。
    • 颁发访问令牌,客户端应用可以使用该令牌访问资源服务器。
  • 类比:认证中心就像是一个“护照签发机构”,用户通过它获取“护照”(访问令牌),然后凭“护照”访问其他国家的“资源”(资源服务器)。

2. 资源服务器(Resource Server)

  • 角色:资源服务器是受保护的 API 服务,提供具体的业务数据。

  • 功能

    • 验证客户端应用提供的访问令牌。
    • 如果令牌有效,返回请求的资源;否则,拒绝访问。
  • 类比:资源服务器就像是一个“海关”,检查用户的“护照”(访问令牌)是否有效,决定是否允许用户进入。

3. 客户端应用(Client Application)

  • 角色:客户端应用是用户直接交互的前端应用或第三方应用。

  • 功能

    • 引导用户到认证中心登录。
    • 获取访问令牌并使用它访问资源服务器。
  • 类比:客户端应用就像是一个“旅行社”,帮助用户获取“护照”(访问令牌),并安排用户访问“资源”(资源服务器)。


二、配置文件详细介绍

1. 认证中心(auth-server)

(1) pom.xml

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

(2) application.yml

server:
  port: 8080
spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password: password
  h2:
    console:
      enabled: true

(3) 配置类

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

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
            .withClient("client-app")
            .secret("{noop}secret")
            .authorizedGrantTypes("authorization_code", "refresh_token")
            .scopes("read")
            .redirectUris("http://localhost:8081/login/oauth2/code/client-app");
    }

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

2. 资源服务器(resource-server)

(1) pom.xml

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

(2) application.yml

server:
  port: 8082

(3) 配置类

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/api/**").authenticated();
    }
}

3. 客户端应用(client-app)

(1) pom.xml

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

(2) application.yml

server:
  port: 8081
spring:
  security:
    oauth2:
      client:
        registration:
          client-app:
            client-id: client-app
            client-secret: secret
            scope: read
            authorization-grant-type: authorization_code
            redirect-uri: http://localhost:8081/login/oauth2/code/client-app
            client-name: client-app
        provider:
          client-app:
            authorization-uri: http://localhost:8080/oauth/authorize
            token-uri: http://localhost:8080/oauth/token
            user-info-uri: http://localhost:8080/userinfo
            user-name-attribute: sub

(3) 配置类

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .oauth2Login();
    }
}

三、跳转流程图解

以下是基于 OAuth 2.0 授权码模式的跳转流程:

+-------------------+       +-------------------+       +-------------------+
|   Client App      |       |   Auth Server     |       |   Resource Server |
|   (localhost:8081)|       |   (localhost:8080)|       |   (localhost:8082)|
+-------------------+       +-------------------+       +-------------------+
         |                          |                          |
         | 1. 访问 /resource        |                          |
         |------------------------->|                          |
         |                          |                          |
         | 2. 重定向到登录页面      |                          |
         |<-------------------------|                          |
         |                          |                          |
         | 3. 用户登录              |                          |
         |------------------------->|                          |
         |                          |                          |
         | 4. 授权码回调            |                          |
         |<-------------------------|                          |
         |                          |                          |
         | 5. 使用授权码获取令牌     |                          |
         |------------------------->|                          |
         |                          |                          |
         | 6. 返回访问令牌           |                          |
         |<-------------------------|                          |
         |                          |                          |
         | 7. 使用令牌访问资源       |                          |
         |---------------------------------------------------->|
         |                          |                          |
         | 8. 返回资源数据           |                          |
         |<----------------------------------------------------|

  • 认证中心:负责用户身份验证和令牌颁发。
  • 资源服务器:提供受保护的 API,验证令牌并返回资源。
  • 客户端应用:引导用户登录并使用令牌访问资源。