django rest框架的单点登录扩展。
djangorestframework-sso的Python项目详细描述
django rest framework sso是django rest framework的扩展,它支持 使用jwt标准在面向微服务的环境中进行单点登录。
此库提供两种JWT令牌:
- 主登录应用程序(aka)的非过期会话令牌。“刷新令牌”)
- 用于访问其他应用程序的短期授权令牌(这些令牌包含主应用程序授予的权限)
客户机应该首先通过发布用户名和密码登录到您的主登录应用程序。客户端将收到一个永久会话令牌,该令牌将允许对同一服务器的后续请求进行身份验证。这些令牌不包含任何权限/授权信息,不能用于SSO到其他应用程序中。
之后,客户端需要使用会话令牌获取并不断更新授权令牌。这些辅助令牌是短期的(15分钟..1小时),包含用户在颁发时拥有的权限。这些令牌用于访问其他服务,然后在令牌的生命周期内信任jwt负载中的权限。
快速启动
将“rest_framework_sso”添加到已安装的应用程序设置中,如下所示:
INSTALLED_APPS = [ ... 'rest_framework_sso', ]
包括会话和授权令牌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身份验证
为了在您的微服务应用程序中自动获取或创建用户帐户, 您可能需要编写自定义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), )
设置
发布并验证myapp和otherapp的令牌的项目设置示例:
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