构建 J2EE 微服务体系结构

我发表了一篇关于单页应用程序(UI)的文章,但在这篇文章中,我将介绍如何使用Spring框架和开源SSO框架Keycloak为J2EE应用程序构建微服务架构。这篇文章将涵盖以下几个方面:

Keycloak 设置
Eureka 服务注册和发现
Spring Cloud API 网关
Spring Security(OAuth2登录)以及与Keycloak的集成
微服务
该代码可在我的 Github 中找到,请先检查docker-compose.yml,以便您可以更轻松地阅读帖子的其余部分。我在这里需要提到的一件事是,在运行 docker 容器之前,您需要将 keycloak 服务器 URL 的 IP 地址替换为您自己的 IP 地址。

version: '3.4'
services:
  api-gateway:
    build:
      context: ./api-gateway
    ports:
      - "8080:8080"
    restart: on-failure
    environment:
      #overriding spring application.properties
      - eureka.client.serviceUrl.defaultZone=http://eureka-server:9091/eureka/
      - keycloak-client.server-url=http://10.0.0.17:18080/auth # use host name or ip of the host machine
    depends_on:
      - eureka-server
  eureka-server:
    build:
      context: ./eureka-server
    ports:
      - "9091:9091"
    restart: on-failure
  microservice-consumer:
    build:
      context: ./microservice-consumer
    ports:
      - "9080:9080"
    restart: on-failure
    environment:
      #overriding spring application.properties
      - eureka.client.serviceUrl.defaultZone=http://eureka-server:9091/eureka/
      - keycloak-client.server-url=http://10.0.0.17:18080/auth # use host name or ip of the host machine
    depends_on:
      - eureka-server
  microservice-producer:
    build:
      context: ./microservice-producer
    ports:
      - "9081:9081"
    restart: on-failure
    environment:
      #overriding spring application.properties
      - eureka.client.serviceUrl.defaultZone=http://eureka-server:9091/eureka/
      - keycloak-client.server-url=http://10.0.0.17:18080/auth # use host name or ip of the host machine
    depends_on:
      - eureka-server
  keycloak:
    image: jboss/keycloak:11.0.0
      volumes:
      - ./keycloak-server/realm-export.json:/tmp/keycloak/config/realm-export.json
    environment:
        KEYCLOAK_USER: admin
        KEYCLOAK_PASSWORD: admin
        KEYCLOAK_IMPORT: /tmp/keycloak/config/realm-export.json
        DB_VENDOR: POSTGRES
        DB_ADDR: postgres
        DB_DATABASE: keycloak
        DB_USER: keycloak
        DB_SCHEMA: public
        DB_PASSWORD: password
    ports:
      - "18080:18080"
    command:
      - "-b"
      - "0.0.0.0"
      - "-Djboss.socket.binding.port-offset=10000"
    restart: on-failure
    depends_on:
      - postgres
  postgres:
      image: postgres
      volumes:
        - postgres_data:/var/lib/postgresql/data
      environment:
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: password
volumes:
    postgres_data:
      name: keycloak_postgres_data
      driver: local

然后,您可以运行以下 cmd 来启动 docker 容器。

docker-compose up --build
  1. 钥匙斗篷
    Keycloak是一个开源的身份和访问管理解决方案。与 Spring Security OAuth2 框架集成非常方便。在这里,我将逐步展示如何设置密钥斗篷服务器。

首先,基于上面的 docker-compose 配置文件,请使用以下 cmd 构建并启动 keycloak 服务器。我导出了一个 JSON 文件(realm-export.json),该文件可供 keycloak docker 容器使用,因此您无需逐步配置。无论如何,我将一一展示该步骤。

docker-compose up --build keycloak

1.1 创建领域
使用 admin/admin 登录 http://localhost:18080/,然后创建一个如下领域,将所有字段保留为默认字段。
在这里插入图片描述
1.2 在上述领域下创建客户端
在这里插入图片描述
如上图所示,我们创建了三个客户端,分别代表 API 网关、微服务消费者和微服务生产者。有两件事需要提及。

首先,将必填字段(Valid Redirect URIs)填写为*,以便我们可以重定向回应用程序中配置的URI。

然后,选择客户端 ID 和 secrete 作为客户端身份验证器,这适用于与 Spring Security OAuth2 客户端集成。
在这里插入图片描述
1.3 创建用户
如下面的屏幕截图所示,我们需要填写一些必要的字段,例如名字、姓氏和电子邮件等。
在这里插入图片描述
2. Eureka Sever — 服务注册
基于 Spring Cloud Eureka 构建服务注册服务器非常简单,我们只需要注解@EnableEurekaServer即可实现。

  1. API 网关
    Spring 框架 5 发布了 Spring Cloud 网关,以取代之前的网关 Spring Cloud Zuul。Spring Cloud Gateway 是建立在 Project Reactor、Spring WebFlux 和 Spring Boot 2.0 之上的新一代非阻塞网关,而 Zuul 是阻塞网关。 因此,在这篇文章中,我使用 Spring Cloud Gateway 作为微服务的 API 网关。

首先,我需要显示application.yml配置文件。

logging:
  level:
    root: WARN
    org.springframework.web: INFO
    org.springframework.security: DEBUG
    org.springframework.security.oauth2: DEBUG
server:
keycloak-client:
  server-url: http://localhost:18080/auth
  realm:  spring-micro-main
spring:
  application:
    name: api-gateway
  security:
    oauth2:
      client:
        registration:
          keycloak:
            provider: keycloak
            client-id: spring-micro-gateway
            client-secret: 756b0558-018b-4809-b478-bd5b4995d325
            authorization-grant-type: authorization_code
            redirect-uri: http://localhost:8080/login/oauth2/code/keycloak
            scope: openid
        provider:
          keycloak:
            authorization-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/auth
            token-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/token
            user-info-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/userinfo
            jwk-set-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/certs
            user-name-attribute: name
            user-info-authentication-method: header
      resourceserver:
        jwt:
          jwk-set-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/certs
  cloud:
    gateway:
      routes:
        - id: microservice-consumer
          uri: lb://microservice-consumer
          predicates:
            - Path=/api/consume/**
          filters:
            - TokenRelay=
            - RemoveRequestHeader=Cookie
        - id: microservice-producer
          uri: lb://microservice-producer
          predicates:
            - Path=/api/produce/**
          filters:
            - TokenRelay=
            - RemoveRequestHeader=Cookie
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:9091/eureka/

3.1 Spring Cloud Gateway中的路由定义
我们为两个微服务定义了两条路由:使用者和生产者。lb://microservice-consumer 意味着它指向基于服务注册服务器 Eureka 的微服务消费者。我们使用 TokenRelay 以便将请求中的access_token传递到微服务资源服务器,该服务器由 Spring Security OAuth2 和 Keycloak 保护。

3.2 Eureka 客户端配置
API 网关还充当 Eureka 客户端,以便它可以与微服务副本一起使用。我们只需要一个注释@EnableEurekaClient并在属性中配置 eureka 服务器 URL。

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:9091/eureka/

3.3 Spring Security OAuth2 以及与 Keycloak 服务器的集成
3.3.1 Spring Security OAuth2
Spring Security 5 的主要功能之一是对 OAuth2 和 OIDC 的原生支持,而不是旧的 Spring Security OAuth 子项目中的旧客户端支持,与 IAM(身份和访问管理)提供商集成变得非常容易。我们需要添加以下依赖项:

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

3.3.2 OAuth2 客户端注册
OAuth 2 客户端的属性以spring.security.oauth2.client.registration andspring.security.

oauth2.client.provider.特别是对于Keycloak,我们必须配置OAuth2提供程序的详细信息,并提供客户端注册的详细信息,如下所示。

spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            provider: keycloak
            client-id: spring-micro-consumer
            client-secret: b2678444-3e56-466d-b035-a6109ca686ca
            authorization-grant-type: authorization_code
            redirect-uri: http://localhost:9080/login/oauth2/code/keycloak
            scope: openid
        provider:
          keycloak:
            authorization-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/auth
            token-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/token
            user-info-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/userinfo
            jwk-set-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/certs
            user-name-attribute: name
            user-info-authentication-method: header
      resourceserver:
        jwt:
          jwk-set-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}/protocol/openid-connect/certs

3.3.3 Spring Security OAuth2 资源服务器
Keycloak使用公钥/私钥对来颁发和验证JWT(JSON Web Token)。具体而言,它使用私钥对访问令牌进行签名,而 OAuth2 客户端使用公钥来验证令牌。

我们需要将 API 网关作为 OAuth2 资源服务器进行保护,以便当请求在 Authorization 标头下带有持有者令牌时,它还可以验证令牌,而不是重定向到 SSO 服务器进行身份验证,然后请求最终可以转到下游微服务。例如,我们可以使用 HTTP 客户端发出请求,如下所示。

GET localhost:8080/api/produce/
Authorization: Bearer <your access token>

3.3.4 启用 OAuth2 登录和资源服务器
要启用 Spring Security OAuth2 登录以及资源服务器,我们需要利用 DSL 方法。

Spring Security 的 OAuth 2.0 登录支持是通过 Spring Security DSL 方法启用的。oauth2Login()

Spring Security 的 Resource Server 支持是通过 Spring Security DSL 方法启用的。oauth2ResourceServer

图示如下:

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SpringSecurityConfig {
    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        // @formatter:off
        http
                .authorizeExchange()
                .anyExchange().authenticated()
                .and()
                .oauth2Login()
                .and()
                .oauth2ResourceServer()
                .jwt();
        return http.build();
        // @formatter:on
    }
}
  1. 微服务
    微服务应受 Keycloak 保护,并作为 OAuth2 资源服务器启用。因此,配置类似于 API 网关。一个关键的区别是,Spring Cloud 网关是建立在 Spring WebFlux 之上的,而我们的微服务是建立在 Spring MVC 之上的。因此,安全配置略有不同,如下图所示。
@Configuration
public class OAuth2ResourceServerConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .oauth2Login()
                .and()
                .oauth2ResourceServer()
                .jwt();
    }
}

就是这样,你就可以开始了。请检查我的 Github 中的源代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值