无需修改即可让你的网站具有认证功能

需求:已有一个content website,域名为easy-test。如何在不修改源码的情况下增加认证功能?
方案:没有什么是加一个中间层不能解决的,如果不行,那就再加一层。
原本:浏览器→easy-test。用户在浏览器中直接访问网站,网站没有认证功能。
现在:浏览器→oauth2-proxy→easy-test。首先将网站配置为仅允许特定请求访问,比如只允许来自oauth2的请求访问。现在用户通过oauth2进行间接访问,同时oauth2利用三方API实现认证(如Google账号,WeChat等),认证通过后转发到easy-test。

使用 oauth2-proxy 为自己的网站提供认证是一个常见的方案。以下是一些基本步骤来帮助你进行设置:

1. 准备 Google OAuth 凭证

  1. 创建项目: 在 Google Cloud Console 中创建一个新的项目。

  2. 启用 API: 启用 "OAuth consent screen" 和 "Credentials"。配置 OAuth 2.0 同意屏幕,记得设定应用名称和支持的邮箱。

  3. 创建 OAuth 客户端 ID:

    • 导航到 “Credentials” 页,点击“Create credentials”,选择“OAuth client ID”。
    • 在“Application type”中选择“Web application”。
    • 设置“Authorized redirect URIs”到 http://<your-oauth2-proxy-domain>/oauth2/callback
  4. 获取客户端ID和客户端密钥,稍后会用到它们进行oauth2-proxy配置。

2. 部署 oauth2-proxy

你可以使用 docker 来运行 oauth2-proxy,它也是最常见的方法之一。

version: '3'
services:
  oauth2-proxy:
    image: quay.io/oauth2-proxy/oauth2-proxy
    container_name: oauth2-proxy
    ports:
      - "4180:4180"
    environment:
      - OAUTH2_PROXY_PROVIDER=google
      - OAUTH2_PROXY_CLIENT_ID=your_google_client_id
      - OAUTH2_PROXY_CLIENT_SECRET=your_google_client_secret
      - OAUTH2_PROXY_REDIRECT_URL=http://your-oauth2-proxy-domain/oauth2/callback 
      - OAUTH2_PROXY_COOKIE_SECRET=random_cookie_secret_base64
      - OAUTH2_PROXY_EMAIL_DOMAINS=*
    command:
      - "--http-address=http://0.0.0.0:4180"
      - "--upstream=http://your-upstream-service"  # e.g. http://easy-test
      - "--cookie-secure=false" # set to true if you're using https

3. 配置你的反向代理(如Nginx或Traefik)

假设你使用 nginx,你可以将请求代理到 oauth2-proxy

server {
    listen 80;
    server_name your-domain.com;  # indicates oauth2-proxy domain

    location / {
        proxy_pass http://localhost:4180;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
    }
}

4. 启动服务

确保你的 oauth2-proxy 和 web server 都启动了,然后访问你的网站。你将在访问网站时被引导到 Google 登录页面,登录成功后会被重定向回你的站点。

5. 调整和测试

根据需要调整 oauth2-proxy 和反代配置,确保所有请求都需通过认证。使用 HTTPS 来增强安全性,并测试通过其他浏览器和账户来验证配置有效性。

通过这些步骤,你应该能够使用 oauth2-proxy 通过 Google 的 OAuth 2.0 为你的网站提供基本的身份验证功能。

请你更具体一点,并结合你先前的配置,包括nginx,oauth2-proxy,比如重定向到oauth2-proxy是因为nginx设置了转发。并假设上游服务地址为cdj.github.io。

好的,我们来具体讨论一下,以假设您的服务地址为 cdj.github.io 为例,详细说明如何将请求通过 nginxoauth2-proxy 进行设置,并解释每个步骤的实际作用。

主要组件

  1. 服务地址: cdj.github.io,这是用户访问的主域名。
  2. oauth2-proxy: 负责处理认证请求并验证用户身份。
  3. nginx: 作为反向代理,通过把请求转发给 oauth2-proxy 来保护实际服务。

访问cdj.github.io时(即访问到nginx),会被转发到oauth2,然后经过认证后访问到oauth2中配置的上游服务。

配置和流程细节

1. Google OAuth Client Setup

在 Google Cloud Console 中:

  • 创建 OAuth 2.0 应用,设置“Authorized redirect URI”为 http://<your-oauth2-proxy-domain>/oauth2/callback (例如,http://cdj.github.io/oauth2/callback)。

2. Nginx 配置

使用 Nginx 做为反向代理服务器,可以帮助在用户访问您的主域名时,将请求重定向到 oauth2-proxy

server {
    listen 80;
    server_name cdj.github.io;

    location / {
        # Forward all requests to oauth2-proxy
        proxy_pass http://localhost:4180;  # oauth2-proxy运行的端口
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
    }
}

3. oauth2-proxy 配置(假设使用 Docker)

创建一个 docker-compose.yaml 来启动 oauth2-proxy:

version: '3'
services:
  oauth2-proxy:
    image: quay.io/oauth2-proxy/oauth2-proxy
    container_name: oauth2-proxy
    environment:
      - OAUTH2_PROXY_PROVIDER=google
      - OAUTH2_PROXY_CLIENT_ID=<your_google_client_id>
      - OAUTH2_PROXY_CLIENT_SECRET=<your_google_client_secret>
      - OAUTH2_PROXY_COOKIE_SECRET=<random_cookie_secret_base64>
      - OAUTH2_PROXY_REDIRECT_URL=http://cdj.github.io/oauth2/callback
      - OAUTH2_PROXY_EMAIL_DOMAINS=*
    ports:
      - "4180:4180"
    command:
      - "--http-address=http://0.0.0.0:4180"
      - "--upstream=http://backend-service"  # 你的后端服务
      - "--cookie-secure=false"  # 若使用 HTTPS, 应设置为 true
      - "--cookie-refresh=1h"

4. 用户访问流程

  1. 用户访问 cdj.github.io:

    • 请求到达 nginx,根据配置转发请求到 oauth2-proxy
  2. oauth2-proxy 确定认证状态:

    • 如果用户没有认证,oauth2-proxy 重定向用户到 Google 的登录页面。
  3. 用户在 Google 登录:

    • 用户输入凭证进行登录。
  4. Google 调用 Redirect URI:

    • Google 在用户登录成功后,通过配置好的 Redirect URI (http://cdj.github.io/oauth2/callback) 把用户带回 oauth2-proxy,并附带授权码。
  5. oauth2-proxy 验证用户:

    • 使用授权码从 Google 获取访问令牌,验证用户身份。
    • 如果成功,设置会话cookie,并将用户重定向到原始请求页面(cdj.github.io)。
  6. 访问受保护资源:

    • 用户现在可以访问 cdj.github.io 上提供的受保护资源,因为 oauth2-proxy 验证已通过,该用户的请求将通过已设置的会话cookie自动授权。

本着这种配置设置,cdj.github.io 的资源被 oauth2-proxynginx 反馈机制加以保护,确保只有经过 Google OAuth 认证的用户才能访问。

这里通过配置好的 Redirect URI (http://cdj.github.io/oauth2/callback) 把用户带回 oauth2-proxy,并附带授权码。oauth2-proxy不是在本地吗(即域名为localhost)?那redirect URI的域名为什么是cdj.github.io?在完成Google认证后,用户是如何成功的访问受保护的资源的?

感谢你的提问,这里的确涉及到一些细节,需要进一步解释清楚。

Redirect URI 的选择与意义

  • Redirect URI 背后的逻辑

    • Redirect URI 是 OAuth 2.0 认证流程的一部分,确保 Google 的 OAuth 服务器知道成功认证后将用户重定向到哪里。
    • 这个URI必须和你在Google开发者控制台中设置的地址一致,以确保安全性和正确性。
  • 为什么是 http://cdj.github.io/oauth2/callback

    • 使用 cdj.github.io 是为了以一种公共方式表达用户访问的域名,以便用户返回时可以正确访问到你的服务。
    • 在你实际的部署中,cdj.github.io 可以被映射到你的反向代理服务器所在的地址(就是nginx代理到了oauth2-proxy),而不是直接反映 oauth2-proxy 的本地运行环境。
    • http://cdj.github.io/oauth2/callback对应http://localhost:4180/oauth2/callback,而localhost:4180就是oauth2-proxy服务的地址。

用户认证后如何访问受保护的资源

  1. 用户认证成功并重定向

    • 当用户在 Google 成功登录后,认证服务器会把用户重定向回“Redirect URI”,通常就是你域名下的某个路径,例如:http://cdj.github.io/oauth2/callback
    • Nginx 代理过来的请求会继续发送到 oauth2-proxy,这个代理方式保证用户是通过浏览器直接访问的。
  2. OAuth2 Proxy 处理重定向请求

    • oauth2-proxy 会处理这个来自 Google 的重定向请求,读取 URL 中附带的授权码。
  3. 交换访问令牌

    • oauth2-proxy 使用这个授权码与 Google 进行通信,通过后台请求换取访问令牌(Access Token)。这一过程确保用户身份的有效性。
  4. 设置用户会话

    • 一旦获取到访问令牌并验证成功,oauth2-proxy 会在用户浏览器中设置一个带有用户身份信息的会话cookie。
    • 这个会话cookie是在同一域下有效,会在每次请求中被自动发送以确认用户身份。
  5. 用户访问受保护的资源

    • 由于您的 nginx 被设置为将所有流量传递给 oauth2-proxy,此后用户的每次请求都会携带会话cookie。
    • oauth2-proxy 会验证该 cookie 是否有效,从而判断是否允许访问受保护的资源。
    • 请求被授权后,oauth2-proxy 会将被验证的请求转发到您的真实服务(backend service)。

这种方式确保您的所有请求都经过身份验证和授权,并提供了一个透明和安全的用户访问路径,从用户的浏览器请求到您的实际服务,确保没有经过认证的用户无法直接访问受保护资源。

请求被授权后,oauth2-proxy 会将被验证的请求转发到您的真实服务(backend service)。那么我需要在oauth2-proxy中配置我的真实服务吗?是如何实现的呢?比如认证成功后,访问http://cdj.github.io/articles,会被nginx重定向到oauth2-proxy(http://localhost:4180),此时发现已经认证过了,接下来应该的步骤是什么?

是的,当使用 oauth2-proxy 来守护你的应用时,你需要在 oauth2-proxy 中配置你的真实后端服务(backend service),以便在成功认证后将请求转发到正确的服务。以下是详细步骤和工作方式:

配置你的真实后端服务在 oauth2-proxy

oauth2-proxy 的配置中,使用 --upstream 参数来指定你的实际服务地址。这是用户请求成功认证后的目的地。

完整的工作流程

前期配置

  1. 配置 oauth2-proxy

    • oauth2-proxy 的启动命令中,使用 --upstream 参数指定你的真实后端服务地址。例如,你可能会有一个后端服务运行在 http://localhost:8080
      command:
        - "--provider=google"
        - "--email-domain=*"
        - "--upstream=http://localhost:8080"  # 指定你的后端服务
        - "--cookie-secret=<random_cookie_secret_base64>"
        - "--cookie-secure=false"  # 在使用 HTTPS 时设置为 true
        - "--http-address=http://0.0.0.0:4180"
      
  2. 配置 nginx

    • 确保 Nginx 将所有对 http://cdj.github.io 的请求转发给 oauth2-proxy,正如之前配置的:
      server {
          listen 80;
          server_name cdj.github.io;
      
          location / {
              proxy_pass http://localhost:4180;
              proxy_set_header Host $host;
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header X-Scheme $scheme;
          }
      }
      

实际请求处理

  1. 用户访问 http://cdj.github.io/articles

    • 用户请求通过 nginx 代理被传递到 oauth2-proxy
  2. oauth2-proxy 检查认证状态

    • oauth2-proxy 检查用户是否已经认证(基于会话cookie)。
    • 如果用户未认证,则重定向用户去Google登录流程。
  3. 认证成功后的处理

    • 如果用户已认证,则请求通过 oauth2-proxy 检察会话cookie的有效性,以确认用户身份。
  4. 转发到真实服务

    • 经验证的请求由 oauth2-proxy 转发至配置的后端服务(http://localhost:8080)。
    • 这个请求会附带原始请求的头信息和认证信息,以在实际服务中继续处理。
  5. 后端服务提供响应

    • 后端服务处理该请求,并返回响应给 oauth2-proxy
    • 之后,oauth2-proxy 将此响应传回客户端,通过 nginx,最终展示给用户。

通过此配置流程,你能够确保 http://cdj.github.io/articles 等资源都经过严格的身份认证,只有通过认证的请求才会被传递给后端服务进行处理,确保资源的安全性和访问控制的有效性。

这样的话,http://cdj.github.io/articles 会被转发到 http://localhost:8080/articles ?相当于除了域名和端口外的内容会被保留?

是的,使用 oauth2-proxy 配合反向代理(如 Nginx)以及后端服务时,你描述的行为是正确的:除域名和端口号外,URL 的其余部分(如路径和查询参数)都将被保留并转发给指定的后端服务。这种行为通常在反向代理的场景中被称为路径保留。

具体请求处理流程

  1. 用户请求:当用户访问 http://cdj.github.io/articles 时:

    • 请求被 Nginx 捕获,并根据你的配置转发给 oauth2-proxy(假设 oauth2-proxy 监听的是 http://localhost:4180)。
  2. 通过认证oauth2-proxy 检查用户的认证状态。如果用户已认证:

    • 请求中的路径(如 /articles)会被保留。
  3. 请求转发:认证通过的请求会被 oauth2-proxy 发送到其上配置的上游(即后端服务),并保持原始路径和查询参数:

    • 例如,如果 --upstream 被设置为 http://localhost:8080,则请求会被转发到 http://localhost:8080/articles
    • 如果 URL 包含查询参数,如 http://cdj.github.io/articles?page=2,那么转发会保持这些参数,如 http://localhost:8080/articles?page=2
  4. 后端服务处理:这样,您的后端服务(运行在 http://localhost:8080)可以直接使用路径 /articles 来正确处理请求。

反向代理路径保留的重要性

  • 透明度:对用户来说,请求路径看起来保持不变,用户不需要了解后端服务器的具体域名或端口。

  • 简洁配置:只需配置一次 --upstream,所有请求都会以相同的方式进行处理。

  • 容易适配:绝大多数 Web 应用和 API 都会根据 URL 的路径来确定如何响应请求,因此保留路径对于应用正常运作是必要的。

通过这种透明且一致的请求转发方式,你可以确保用户请求在经过 oauth2-proxy 和 Nginx 的传递和处理过程中始终保留原始路径结构,而只需关注域名和端口的对应配置。这样既能保证安全的认证,也能确保后端服务的逻辑正常运行。

赞赏