django rest框架的单点登录扩展。

djangorestframework-sso的Python项目详细描述


django rest framework sso是django rest framework的扩展,它支持 使用jwt标准在面向微服务的环境中进行单点登录。

此库提供两种JWT令牌:

  1. 主登录应用程序(aka)的非过期会话令牌。“刷新令牌”)
  2. 用于访问其他应用程序的短期授权令牌(这些令牌包含主应用程序授予的权限)

客户机应该首先通过发布用户名和密码登录到您的主登录应用程序。客户端将收到一个永久会话令牌,该令牌将允许对同一服务器的后续请求进行身份验证。这些令牌不包含任何权限/授权信息,不能用于SSO到其他应用程序中。

之后,客户端需要使用会话令牌获取并不断更新授权令牌。这些辅助令牌是短期的(15分钟..1小时),包含用户在颁发时拥有的权限。这些令牌用于访问其他服务,然后在令牌的生命周期内信任jwt负载中的权限。

快速启动

  1. 将“rest_framework_sso”添加到已安装的应用程序设置中,如下所示:

    INSTALLED_APPS = [
        ...
        'rest_framework_sso',
    ]
    
  2. 包括会话和授权令牌URL:

    from rest_framework_sso.views import obtain_session_token, obtain_authorization_token
    
    urlpatterns = [
        ...
        url(r'^session/', obtain_session_token),
        url(r'^authorize/', obtain_authorization_token),
    ]
    

授权令牌中的其他数据

例如,您可能希望在JWT授权令牌中包含帐户字段, 以便其他应用程序了解用户的权限。为此,您可能需要覆盖 获取AuthorizationTokenView和AuthorizationTokenSerializer:

class ObtainAuthorizationTokenView(rest_framework_sso.views.ObtainAuthorizationTokenView):
    """
    Returns a JSON Web Token that can be used for authenticated requests.
    """
    serializer_class = AuthorizationTokenSerializer


class AuthorizationTokenSerializer(serializers.Serializer):
    account = serializers.HyperlinkedRelatedField(
        queryset=Account.objects.all(),
        required=True,
        view_name='api:account-detail',
    )

    class Meta:
        fields = ['account']

替换url conf中的authorization token视图:

urlpatterns = [
    url(r'^authorize/$', ObtainAuthorizationTokenView.as_view()),
    ...
]

accountkeyword参数添加到create_authorization_payload函数:

from rest_framework_sso import claims

def create_authorization_payload(session_token, user, account, **kwargs):
    return {
        claims.TOKEN: claims.TOKEN_AUTHORIZATION,
        claims.SESSION_ID: session_token.pk,
        claims.USER_ID: user.pk,
        claims.EMAIL: user.email,
        'account': account.pk,
    }

您需要在设置中激活此功能:

REST_FRAMEWORK_SSO = {
    'CREATE_AUTHORIZATION_PAYLOAD': 'myapp.authentication.create_authorization_payload',
    ...
}

JWT身份验证

为了在您的微服务应用程序中自动获取或创建用户帐户, 您可能需要编写自定义jwt负载身份验证功能:

from django.contrib.auth import get_user_model
from rest_framework_sso import claims

def authenticate_payload(payload):
    user_model = get_user_model()
    user, created = user_model.objects.get_or_create(
        service=payload.get(claims.ISSUER),
        external_id=payload.get(claims.USER_ID),
    )
    if not user.is_active:
        raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))
    return user

在rest_framework_sso设置中启用authenticate_payload功能:

REST_FRAMEWORK_SSO = {
    'AUTHENTICATE_PAYLOAD': 'otherapp.authentication.authenticate_payload',
    ...
}

在rest_框架设置中启用jwt身份验证:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_sso.authentication.JWTAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        ...
    ),
    ...
}

已通过jwtauthentication成功验证的请求包含 request.auth变量中的JWT有效载荷数据。此数据可用于 处理权限的API视图/视图集,例如:

from rest_framework_sso import claims

class UserViewSet(viewsets.ReadOnlyModelViewSet):
    serializer_class = UserSerializer
    queryset = User.objects.none()

    def get_queryset(self):
        if not request.user.is_authenticated or not request.auth:
            return self.none()
        return User.objects.filter(
            service=request.auth.get(claims.ISSUER),
            external_id=request.auth.get(claims.USER_ID),
        )

设置

发布并验证myappotherapp的令牌的项目设置示例:

REST_FRAMEWORK_SSO = {
    'CREATE_AUTHORIZATION_PAYLOAD': 'myapp.authentication.create_authorization_payload',
    'IDENTITY': 'myapp',
    'SESSION_AUDIENCE': ['myapp'],
    'AUTHORIZATION_AUDIENCE': ['myapp', 'otherapp'],
    'ACCEPTED_ISSUERS': ['myapp'],
    'PUBLIC_KEYS': {
        'myapp': 'keys/myapp-20180101.pem',  # both private/public key in same file
    },
    'PRIVATE_KEYS': {
        'myapp': 'keys/myapp-20180101.pem',  # both private/public key in same file
    },
}

仅接受由myapp签名的令牌的项目的示例设置otherapp的公钥

REST_FRAMEWORK_SSO = {
    'AUTHENTICATE_PAYLOAD': 'otherapp.authentication.authenticate_payload',
    'VERIFY_SESSION_TOKEN': False,
    'IDENTITY': 'otherapp',
    'ACCEPTED_ISSUERS': ['myapp'],
    'PUBLIC_KEYS': {
        'myapp': 'keys/myapp-20180101.pem',  # only public key in this file
    },
}

设置参数及其默认值的完整列表:

REST_FRAMEWORK_SSO = {
    'CREATE_SESSION_PAYLOAD': 'rest_framework_sso.utils.create_session_payload',
    'CREATE_AUTHORIZATION_PAYLOAD': 'rest_framework_sso.utils.create_authorization_payload',
    'ENCODE_JWT_TOKEN': 'rest_framework_sso.utils.encode_jwt_token',
    'DECODE_JWT_TOKEN': 'rest_framework_sso.utils.decode_jwt_token',
    'AUTHENTICATE_PAYLOAD': 'rest_framework_sso.utils.authenticate_payload',

    'ENCODE_ALGORITHM': 'RS256',
    'DECODE_ALGORITHMS': None,
    'VERIFY_SIGNATURE': True,
    'VERIFY_EXPIRATION': True,
    'VERIFY_SESSION_TOKEN': True,
    'EXPIRATION_LEEWAY': 0,
    'SESSION_EXPIRATION': None,
    'AUTHORIZATION_EXPIRATION': datetime.timedelta(seconds=300),

    'IDENTITY': None,
    'SESSION_AUDIENCE': None,
    'AUTHORIZATION_AUDIENCE': None,
    'ACCEPTED_ISSUERS': None,
    'KEY_STORE_ROOT': None,
    'PUBLIC_KEYS': {},
    'PRIVATE_KEYS': {},

    'AUTHENTICATE_HEADER': 'JWT',
}

生成RSA密钥

您可以使用openssl生成您的公钥/私钥对:

$ openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
$ openssl rsa -pubout -in private_key.pem -out public_key.pem
$ cat private_key.pem public_key.pem > keys/myapp-20180101.pem

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何隐藏actionbar和显示选项卡   java将触摸事件从回收器传递到其父LinearLayout   springboot应用程序中的java enable XFrameOptions标头(不含spring security)   java将十进制128序列化为JSON   java将给定时间转换为GMT   java如何解决SSL握手异常   java哪些平台的缓冲区大小有限?   java如何使用IDE在storm production集群中提交拓扑   Android Javaİmageview的进展   JAVA网使用Spring PathMatchingResourcePatternResolver时出现URI语法异常   java如果有人试图访问我的JSP页面,如何首先显示登录页面?   带水平滚动的java嵌套回收视图   java有可能将Hashmap get和put结合起来吗?   java为什么在计算两毫秒时间戳之间的差时使用模运算符?   从字符串Java中提取葡萄牙语日期   java为什么dispatchTouchEvent避免在屏幕上单击?