django-allauth是否支持OIDC退信式登出?自定义实现无效求助
解决Django-allauth OIDC Backchannel Logout无效的问题
你的核心问题在于只删除了自定义的UserSession模型记录,但Django的用户登录状态依赖内置的Session模型,以及可能的缓存会话存储,直接删自定义模型不会让用户的登录会话失效。此外,宽泛的异常捕获会掩盖具体错误,导致你无法定位问题。
修正后的实现步骤:
替换会话查询逻辑,操作Django内置Session模型
Django的登录会话存储在django.contrib.sessions.models.Session中,需要通过用户ID关联找到所有会话并删除:from django.contrib.sessions.models import Session from django.contrib.auth import get_user_model from allauth.socialaccount.models import SocialAccount, SocialToken import jwtkit @require_POST @login_not_required def backchannel_logout(request, provider_id): logout_token = request.POST.get("logout_token") if not logout_token: return HttpResponse("Missing logout_token", status=400) try: openid_adapter = MyCustomOpenIDAdapter(request, provider_id) openid_config = openid_adapter.openid_config identity_data = jwtkit.verify_and_decode( credential=logout_token, keys_url=openid_config["jwks_uri"], issuer=openid_config["issuer"], audience=[openid_adapter.get_provider().app.client_id], lookup_kid=jwtkit.lookup_kid_jwk, ) sub = identity_data["sub"] # 通过sub找到关联的用户 social_account = SocialAccount.objects.get(uid=sub) user = social_account.user User = get_user_model() # 找到该用户的所有Django会话 user_sessions = [] for session in Session.objects.all(): try: session_data = session.get_decoded() if session_data.get('_auth_user_id') == str(user.id): user_sessions.append(session) except Exception: continue # 删除会话记录 for session in user_sessions: session.delete() # 可选:吊销用户的Social Token(如果需要完全终止OIDC关联) SocialToken.objects.filter(account__user=user).delete() return HttpResponse("Backchannel logout successful", status=200) # 捕获具体异常,便于调试 except SocialAccount.DoesNotExist: return HttpResponse("Associated user not found", status=404) except jwtkit.InvalidTokenError as e: return HttpResponse(f"Invalid logout token: {str(e)}", status=400) except Exception as e: return HttpResponse(f"Backchannel logout failed: {str(e)}", status=500)处理缓存会话存储(如果启用)
如果你的Django配置了SESSION_ENGINE = 'django.contrib.sessions.backends.cache'或cached_db,需要额外清理缓存中的会话:from django.core.cache import cache # 在删除数据库会话后添加: for session in user_sessions: cache.delete(f"django.contrib.sessions.cache.{session.session_key}")排查手动删除会话仍能访问Admin的问题
手动删Session后用户还能访问Admin,通常是因为:- 浏览器缓存了会话Cookie:可以强制浏览器清除Cookie,或者设置
SESSION_EXPIRE_AT_BROWSER_CLOSE = True(在settings.py中) - 会话存储在缓存而非数据库:确保同时清理缓存中的会话记录
- Admin使用了持久化会话:检查
SESSION_COOKIE_AGE配置,确保会话过期时间合理
- 浏览器缓存了会话Cookie:可以强制浏览器清除Cookie,或者设置
内容的提问来源于stack exchange,提问作者Harold Holsappel
相关产品推荐
相关产品推荐

