• frp使用oidc认证和搭建


    frp 是什么?

    frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网

    github源码:https://github.com/fatedier/frp/

    官方文档:概览 | frp

    oidc认证

    frp一般是使用token认证,但是token过于简单,因此,决定使用oidc进行认证

    OIDC 是 OpenID Connect 的简称,验证流程参考 Client Credentials Grant

    oidc搭建

    本次是基于Django进行搭建

    依赖文件requirement.txt如下

    1. Django==4.1
    2. django-cors-headers==3.13.0
    3. django-oauth-toolkit==2.1.0
    4. djangorestframework==3.13.1
    5. PyJWT==2.4.0

    主要使用的是 django-oauth-toolkit 模块,该模块官方文档 Welcome to Django OAuth Toolkit Documentation — Django OAuth Toolkit 2.1.0 documentation

    然后根据文档进行操作

     1.启动一个新的 Django 项目并"rest_framework"和"oauth2_provider"添加到您的INSTALLED_APPS设置中

    1. INSTALLED_APPS = (
    2. 'django.contrib.admin',
    3. ...
    4. 'oauth2_provider',
    5. 'rest_framework',
    6. )

    2.现在我们需要告诉 Django REST Framework 使用新的身份验证后端。请在settings.py模块的末尾添加以下行

    1. REST_FRAMEWORK = {
    2. 'DEFAULT_AUTHENTICATION_CLASSES': (
    3. 'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
    4. ),
    5. 'DEFAULT_PERMISSION_CLASSES': (
    6. 'rest_framework.permissions.IsAuthenticated',
    7. )
    8. }

     3.创建一个简单的 API 来访问用户和组

     a,创建一个oauth.py文件,内容如下

    1. #!/usr/bin/env python
    2. # -*- coding:utf-8 -*-
    3. # project : xfrp
    4. # filename : oauth.py
    5. # author : ly_13
    6. # date : 2022/9/2
    7. from django.contrib.auth.models import User, Group
    8. from rest_framework import generics, permissions, serializers
    9. from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope, TokenHasScope
    10. # first we define the serializers
    11. class UserSerializer(serializers.ModelSerializer):
    12. class Meta:
    13. model = User
    14. fields = ('username', 'email', "first_name", "last_name")
    15. class GroupSerializer(serializers.ModelSerializer):
    16. class Meta:
    17. model = Group
    18. fields = ("name",)
    19. # Create the API views
    20. class UserList(generics.ListCreateAPIView):
    21. permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    22. queryset = User.objects.all()
    23. serializer_class = UserSerializer
    24. class UserDetails(generics.RetrieveAPIView):
    25. permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    26. queryset = User.objects.all()
    27. serializer_class = UserSerializer
    28. class GroupList(generics.ListAPIView):
    29. permission_classes = [permissions.IsAuthenticated, TokenHasScope]
    30. required_scopes = ['groups']
    31. queryset = Group.objects.all()
    32. serializer_class = GroupSerializer

    b.添加URL

    1. from django.contrib import admin
    2. from django.urls import path, include
    3. from api.views.oauth import UserList, UserDetails, GroupList
    4. admin.autodiscover()
    5. urlpatterns = [
    6. path("admin/", admin.site.urls),
    7. path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
    8. path('users/', UserList.as_view()),
    9. path('users//', UserDetails.as_view()),
    10. path('groups/', GroupList.as_view()),
    11. ]

    4,添加oauth配置信息 到settings.py模块中

     OIDC还需要jwt令牌签名算法,使用的是rs256 非对称加密,因此还需要一个rsa私钥,可以通过openssl命令生成

    openssl genrsa -out oidc.key 4096

     注意:此密钥的内容必须保密。不要将它放在您的设置中并将其提交给版本控制!

    1. from oauthlib.oauth2.rfc6749.tokens import signed_token_generator
    2. OAUTH2_PROVIDER = {
    3. "OIDC_ENABLED": True,
    4. "OIDC_RSA_PRIVATE_KEY": open(os.path.join(BASE_DIR, 'oidc.key'), 'r').read(),
    5. "SCOPES": {
    6. "openid": "OpenID Connect scope",
    7. "read": 'Read scope',
    8. 'write': 'Write scope',
    9. 'groups': 'Access to your groups'
    10. },
    11. "EXTRA_SERVER_KWARGS": {
    12. "token_generator": signed_token_generator(open(os.path.join(BASE_DIR, 'oidc.key'), 'r').read(),
    13. **{'iss': 'http://10.66.8.100:8000/o', 'aud': 'openid'})
    14. },
    15. }

    5,迁移数据,并创建管理员用户

    1. python manage.py migrate
    2. python manage.py createsuperuser
    3. python manage.py runserver

     6,访问admin,然后注册新的应用程序

    http://localhost:8000/admin

    然后再访问

    http://localhost:8000/o/applications/

    a.进行注册应用

     b.配置frps服务端,编写frps.ini文件

    1. [common]
    2. bind_port = 8888
    3. authentication_method = oidc
    4. oidc_issuer = http://10.66.8.100:8000/o
    5. oidc_audience = openid

    c.配置frpc客户端,编写frpc.ini文件

    1. [common]
    2. server_addr = 10.66.8.100
    3. server_port = 8888
    4. authentication_method = oidc
    5. oidc_client_id = Aybonk9RoG1I6YzTLKUDnPXU647rtJymig0I2PPj
    6. oidc_client_secret = fNPvjFbZv6Q0IUwE4o2QAHAWjtdlQbgO75RjU3IbKEdythlKmUu3ZShlO8juOhsxCbE7U9gAgXQTbUMsoXt5YrshAt2CwARSz63T5OfnbhwPNl8HtsdqfG2HMFRjMaCK
    7. oidc_audience = openid
    8. oidc_token_endpoint_url = http://10.66.8.100:8000/o/token/
    9. [nginx]
    10. type = tcp
    11. local_ip = 127.0.0.1
    12. local_port = 80
    13. remote_port = 29999

     d.启动服务端

     会发现django服务有请求如下

     e.启动客户端

    客户端也正常启动,没有报错

     会发现django服务有请求如下

     说明请求成功,客户端的端口也已经映射到服务器上面了

    错误解决

    1.token格式不对,compact JWS format must have three parts

    1. 2022/09/05 08:28:55 [E] [service.go:340] invalid OIDC token in login: oidc: malformed jwt: square/go-jose: compact JWS format must have three parts
    2. 2022/09/05 08:28:55 [W] [service.go:128] login to server failed: invalid OIDC token in login: oidc: malformed jwt: square/go-jose: compact JWS format must have three parts
    3. invalid OIDC token in login: oidc: malformed jwt: square/go-jose: compact JWS format must have three parts

    这个需要oidc返回jwt格式的数据,也就是 xxx.xxx.xxx 类似用电分割的加密数据

    2.iss不一致,id token issued by a different provider

    1. 2022/09/05 08:30:50 [E] [service.go:340] invalid OIDC token in login: oidc: id token issued by a different provider, expected "http://127.0.0.1:8000/o" got ""
    2. 2022/09/05 08:30:50 [W] [service.go:128] login to server failed: invalid OIDC token in login: oidc: id token issued by a different provider, expected "http://127.0.0.1:8000/o" got ""
    3. invalid OIDC token in login: oidc: id token issued by a different provider, expected "http://127.0.0.1:8000/o" got ""

    这个需要在生成jwt的时候,加上iss字段

    3.audience不正确,oidc: expected audience "openid"

    1. 2022/09/05 08:32:17 [E] [service.go:340] invalid OIDC token in login: oidc: expected audience "openid" got []
    2. 2022/09/05 08:32:17 [W] [service.go:128] login to server failed: invalid OIDC token in login: oidc: expected audience "openid" got []
    3. invalid OIDC token in login: oidc: expected audience "openid" got []

    这个需要在生成jwt的时候,加上openid字段,并且和配置文件保持一致

    参考文档

    OpenID Connect — Django OAuth Toolkit 2.1.0 documentation

    文档 | frp

  • 相关阅读:
    【剑指offer系列】49. 丑数
    Cent OS 7下部署zabbix5.0
    Django常见面试题总结(二)
    VUE+Spring Boot前后端分离开发实战(六):基于RABC权限通用后台管理系统-给角色动态分配权限和用户
    计算机毕业设计Java的创意项目众筹平台的设计与开发(源码+系统+mysql数据库+lw文档)
    8月25日计算机视觉理论学习笔记——R-FCN、YOLO
    纯前端导出word手写复杂表格,并还原成word。百分百还原表格。一文搞定前端表格导出为word
    MongoDB聚合运算符:$week
    三、创建脚手架和脚手架分析
    简单的股票行情展示演示(一) - 实时标的数据
  • 原文地址:https://blog.csdn.net/ly1358152944/article/details/126712406