需求:已有一个content website,域名为easy-test。如何在不修改源码的情况下增加认证功能?
方案:没有什么是加一个中间层不能解决的,如果不行,那就再加一层。
原本:浏览器→easy-test。用户在浏览器中直接访问网站,网站没有认证功能。
现在:浏览器→oauth2-proxy→easy-test。首先将网站配置为仅允许特定请求访问,比如只允许来自oauth2的请求访问。现在用户通过oauth2进行间接访问,同时oauth2利用三方API实现认证(如Google账号,WeChat等),认证通过后转发到easy-test。
使用 oauth2-proxy
为自己的网站提供认证是一个常见的方案。以下是一些基本步骤来帮助你进行设置:
1. 准备 Google OAuth 凭证
-
创建项目: 在 Google Cloud Console 中创建一个新的项目。
-
启用 API: 启用 "OAuth consent screen" 和 "Credentials"。配置 OAuth 2.0 同意屏幕,记得设定应用名称和支持的邮箱。
-
创建 OAuth 客户端 ID:
- 导航到 “Credentials” 页,点击“Create credentials”,选择“OAuth client ID”。
- 在“Application type”中选择“Web application”。
- 设置“Authorized redirect URIs”到
http://<your-oauth2-proxy-domain>/oauth2/callback
。
-
获取客户端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
为例,详细说明如何将请求通过 nginx
和 oauth2-proxy
进行设置,并解释每个步骤的实际作用。
主要组件
- 服务地址:
cdj.github.io
,这是用户访问的主域名。 - oauth2-proxy: 负责处理认证请求并验证用户身份。
- 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. 用户访问流程
-
用户访问
cdj.github.io
:- 请求到达
nginx
,根据配置转发请求到oauth2-proxy
。
- 请求到达
-
oauth2-proxy 确定认证状态:
- 如果用户没有认证,
oauth2-proxy
重定向用户到 Google 的登录页面。
- 如果用户没有认证,
-
用户在 Google 登录:
- 用户输入凭证进行登录。
-
Google 调用 Redirect URI:
- Google 在用户登录成功后,通过配置好的 Redirect URI (http://cdj.github.io/oauth2/callback) 把用户带回
oauth2-proxy
,并附带授权码。
- Google 在用户登录成功后,通过配置好的 Redirect URI (http://cdj.github.io/oauth2/callback) 把用户带回
-
oauth2-proxy 验证用户:
- 使用授权码从 Google 获取访问令牌,验证用户身份。
- 如果成功,设置会话cookie,并将用户重定向到原始请求页面(
cdj.github.io
)。
-
访问受保护资源:
- 用户现在可以访问
cdj.github.io
上提供的受保护资源,因为oauth2-proxy
验证已通过,该用户的请求将通过已设置的会话cookie自动授权。
- 用户现在可以访问
本着这种配置设置,cdj.github.io
的资源被 oauth2-proxy
和 nginx
反馈机制加以保护,确保只有经过 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服务的地址。
- 使用
用户认证后如何访问受保护的资源
-
用户认证成功并重定向:
- 当用户在 Google 成功登录后,认证服务器会把用户重定向回“Redirect URI”,通常就是你域名下的某个路径,例如:
http://cdj.github.io/oauth2/callback
。 - Nginx 代理过来的请求会继续发送到
oauth2-proxy
,这个代理方式保证用户是通过浏览器直接访问的。
- 当用户在 Google 成功登录后,认证服务器会把用户重定向回“Redirect URI”,通常就是你域名下的某个路径,例如:
-
OAuth2 Proxy 处理重定向请求:
oauth2-proxy
会处理这个来自 Google 的重定向请求,读取 URL 中附带的授权码。
-
交换访问令牌:
oauth2-proxy
使用这个授权码与 Google 进行通信,通过后台请求换取访问令牌(Access Token)。这一过程确保用户身份的有效性。
-
设置用户会话:
- 一旦获取到访问令牌并验证成功,
oauth2-proxy
会在用户浏览器中设置一个带有用户身份信息的会话cookie。 - 这个会话cookie是在同一域下有效,会在每次请求中被自动发送以确认用户身份。
- 一旦获取到访问令牌并验证成功,
-
用户访问受保护的资源:
- 由于您的
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
参数来指定你的实际服务地址。这是用户请求成功认证后的目的地。
完整的工作流程
前期配置
-
配置
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"
- 在
-
配置
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; } }
- 确保 Nginx 将所有对
实际请求处理
-
用户访问
http://cdj.github.io/articles
:- 用户请求通过
nginx
代理被传递到oauth2-proxy
。
- 用户请求通过
-
oauth2-proxy
检查认证状态:oauth2-proxy
检查用户是否已经认证(基于会话cookie)。- 如果用户未认证,则重定向用户去Google登录流程。
-
认证成功后的处理:
- 如果用户已认证,则请求通过
oauth2-proxy
检察会话cookie的有效性,以确认用户身份。
- 如果用户已认证,则请求通过
-
转发到真实服务:
- 经验证的请求由
oauth2-proxy
转发至配置的后端服务(http://localhost:8080
)。 - 这个请求会附带原始请求的头信息和认证信息,以在实际服务中继续处理。
- 经验证的请求由
-
后端服务提供响应:
- 后端服务处理该请求,并返回响应给
oauth2-proxy
。 - 之后,
oauth2-proxy
将此响应传回客户端,通过nginx
,最终展示给用户。
- 后端服务处理该请求,并返回响应给
通过此配置流程,你能够确保 http://cdj.github.io/articles
等资源都经过严格的身份认证,只有通过认证的请求才会被传递给后端服务进行处理,确保资源的安全性和访问控制的有效性。
这样的话,http://cdj.github.io/articles 会被转发到 http://localhost:8080/articles ?相当于除了域名和端口外的内容会被保留?
是的,使用 oauth2-proxy
配合反向代理(如 Nginx)以及后端服务时,你描述的行为是正确的:除域名和端口号外,URL 的其余部分(如路径和查询参数)都将被保留并转发给指定的后端服务。这种行为通常在反向代理的场景中被称为路径保留。
具体请求处理流程
-
用户请求:当用户访问
http://cdj.github.io/articles
时:- 请求被 Nginx 捕获,并根据你的配置转发给
oauth2-proxy
(假设oauth2-proxy
监听的是http://localhost:4180
)。
- 请求被 Nginx 捕获,并根据你的配置转发给
-
通过认证:
oauth2-proxy
检查用户的认证状态。如果用户已认证:- 请求中的路径(如
/articles
)会被保留。
- 请求中的路径(如
-
请求转发:认证通过的请求会被
oauth2-proxy
发送到其上配置的上游(即后端服务),并保持原始路径和查询参数:- 例如,如果
--upstream
被设置为http://localhost:8080
,则请求会被转发到http://localhost:8080/articles
。 - 如果 URL 包含查询参数,如
http://cdj.github.io/articles?page=2
,那么转发会保持这些参数,如http://localhost:8080/articles?page=2
。
- 例如,如果
-
后端服务处理:这样,您的后端服务(运行在
http://localhost:8080
)可以直接使用路径/articles
来正确处理请求。
反向代理路径保留的重要性
-
透明度:对用户来说,请求路径看起来保持不变,用户不需要了解后端服务器的具体域名或端口。
-
简洁配置:只需配置一次
--upstream
,所有请求都会以相同的方式进行处理。 -
容易适配:绝大多数 Web 应用和 API 都会根据 URL 的路径来确定如何响应请求,因此保留路径对于应用正常运作是必要的。
通过这种透明且一致的请求转发方式,你可以确保用户请求在经过 oauth2-proxy
和 Nginx 的传递和处理过程中始终保留原始路径结构,而只需关注域名和端口的对应配置。这样既能保证安全的认证,也能确保后端服务的逻辑正常运行。