问题描述
早上好或下午好,甚至晚上好!
我一直在尝试使用OAuth Toolkit with Django 实现资源服务器与身份验证服务器的分离,但我被卡住了。
尝试过:
首先,我已经尝试了以下方法:
-
按照此 tutorial 的教程进行操作,它在使用python manage.py runserver 为项目提供服务时很有效。
-
整个结构是我使用邮递员作为客户端并向资源服务器请求并使用身份验证服务器检查经过身份验证的用户所以在资源和认证服务器之间存在内省过程。
问题:
正如我所提到的,当我使用 python manage.py runserver 为项目提供服务时,整个想法才有效。当使用Nginx和Gunicorn在Docker-Compose中部署项目服务项目时,头痛来了。
这是最后一个错误 - 超过最大重试次数,网址:/o/introspect/
当我回溯到根目录时 - 自省:在令牌查找中 POST 到 localhost:8000/o/introspect/ 失败
这是客户端应用程序中的错误 - “未提供身份验证凭据。”
我发现当访问令牌过期或撤销并且系统尝试为资源获取新的访问令牌时会发生此问题来自认证服务器的服务器。
不知何故,对我来说,内省过程因未知原因而失败!
以前有人撞过这堵墙吗?
编辑:(2021 年 3 月 4 日星期四)
我发现了另一个可以与确切问题更相关的原因!
作为 docker compose 创建的服务,每个服务服务于一个由项目(Django)镜像组成的容器。因此,每个项目都是相互隔离的!
这会导致 A 项目更难请求到 B 项目,因为 B 项目的端口在 A 项目中无法访问。
一个潜在的解决方案可能是使用 Nginx 服务器代理名称(它将与 docker compose 中的每个服务的名称相同)来发出请求。
我还在努力解决这个问题!如果有人可以提供帮助,那将不胜感激!
编辑:(台湾 2021 年 3 月 4 日星期四下午 5:07)问题已解决
解决方案已演示!
解决方法
阅读之前:此解决方案是使用 Django OAuth 工具包处理项目,该工具包与 Docker-Compose 一起部署,发生了失败的内省请求问题
那么首先,让我向您演示 docker compose 结构:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.SlotsViewHolder> {
ArrayList<String> slots;
public CustomAdapter(ArrayList<String> slots) {
this.slots = slots;
}
@NonNull
@Override
public SlotsViewHolder onCreateViewHolder(@NonNull ViewGroup parent,int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.available_slots_list,parent,false);
return new CustomAdapter.SlotsViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull SlotsViewHolder holder,int position) {
holder.tvSlots.setText(slots.get(position));
}
@Override
public int getItemCount() {
return slots.size();
}
public class SlotsViewHolder extends RecyclerView.ViewHolder {
TextView tvSlots;
public SlotsViewHolder(@NonNull View itemView) {
super(itemView);
tvSlots = itemView.findViewById(R.id.tv_slots);
}
}
docker-compose yml 文件中有两个处理 Django 网络的 Nginx 服务器服务 ShopDjangoBN_Nginx 和 OAuthDjangoBN_Nginx!一般来说,如果我们服务的项目没有docker-compose和nginx,就不会遇到这个问题。 但是,我想在使用 docker 技术进行部署时会遇到这个问题。
要设置Separate Server的想法,你需要按照这个tutorial,你需要在资源服务器项目的Django设置文件中完成以下代码:
version: "3.4"
x-service-volumes: &service-volumes
- ./:/usr/proj/:rw,cached
services:
ShopDjangoBN_Nginx:
image: ${DJ_NGINX_IMAGE}
ports:
- 8001:8001
volumes: *service-volumes
environment:
- NGINX_SHOP_HOST=${NGINX_SHOP_HOST}
depends_on:
- "ShopDjangoBN"
ShopDjangoBN:
image: ${SHOP_DJANGO_IMAGE}
command: gunicorn -w 2 -b 0.0.0.0:8001 main.wsgi:application
volumes: *service-volumes
depends_on:
- "ShopDjangoBN_Migrate"
expose:
- 8001
ShopDjangoBN_CollectStatic:
image: ${SHOP_DJANGO_IMAGE}
command: python manage.py collectstatic --noinput
volumes: *service-volumes
ShopDjangoBN_Migrate:
image: ${SHOP_DJANGO_IMAGE}
command: python manage.py migrate
volumes: *service-volumes
OAuthDjangoBN_Nginx:
image: ${DJ_NGINX_IMAGE}
ports:
- 8000:8000
volumes: *service-volumes
environment:
- NGINX_OAUTH_HOST=${NGINX_OAUTH_HOST}
depends_on:
- "OAuthDjangoBN"
OAuthDjangoBN:
image: ${O_AUTH_DJANGO_IMAGE}
command: gunicorn -w 2 -b 0.0.0.0:8000 main.wsgi:application
volumes: *service-volumes
depends_on:
- "OAuthDjangoBN_Migrate"
expose:
- 8000
OAuthDjangoBN_CollectStatic:
image: ${O_AUTH_DJANGO_IMAGE}
command: python manage.py collectstatic --noinput
volumes: *service-volumes
OAuthDjangoBN_Migrate:
image: ${O_AUTH_DJANGO_IMAGE}
command: python manage.py migrate
volumes: *service-volumes
volumes:
auth-data:
shop-data:
static-volume:
media-volume:
这里的关键是 'RESOURCE_SERVER_INTROSPECTION_URL' 变量!此变量用于从资源向 Auth 服务器请求 Introspection Request,因此,建议正确设置此 url,并且它必须是 Auth 服务器中的内省端点。
接下来,如果您还记得,OAuthDjangoBN_Nginx,它处理任何对 Auth Server 的请求,是一个反向代理服务!从技术上讲,OAuthDjangoBN_Nginx 将成为我们的身份验证服务器主机。所以......资源服务器Django设置文件中的内省网址将如下所示:
OAUTH2_PROVIDER = {
...
'RESOURCE_SERVER_INTROSPECTION_URL': 'https://example.org/o/introspect/','RESOURCE_SERVER_AUTH_TOKEN': '3yUqsWtwKYKHnfivFcJu',# OR this but not both:
#'RESOURCE_SERVER_INTROSPECTION_CREDENTIALS' ('rs_client_id','rs_client_secret'),...
}
和 nginx.conf
'RESOURCE_SERVER_INTROSPECTION_URL': 'https://OAuthDjangoBN_Nginx:<port>/o/introspect/'
这个 proxy_set_header 最好用 env 变量设置,我在互联网上找到了一些解决方案,所以不会有问题。设置也很重要,因为反向主机名将是 OAuthDjangoBN_Nginx:,它不会被识别为有效的主机名,因此,设置它!
upstream OAuthDjangoBN {
server OAuthDjangoBN:8000;
}
server {
listen 8000;
location / {
proxy_pass http://OAuthDjangoBN;
# proxy_set_header Host $NGINX_SHOP_HOST;
proxy_set_header Host "localhost:8000";
proxy_redirect off;
}
location /static/ {
alias /usr/proj/OAuthDjangoBN/static/;
}
}
好的,如果有人遇到或将遇到相同的问题,我认为这个想法可以作为解决方案。我也相信这仍然是一个混乱。如果你撞到墙,请告诉我!