Django应用使用ms_identity_web.login_required返回401而非跳转登录页
Django + ms_identity_web 认证跳转问题
我用Django开发的应用,通过ms_identity_web对接Azure AD做认证,认证功能正常,但未登录时直接访问带@ms_identity_web.login_required装饰器的受保护页面,会返回401错误,不像Django原生@login_required那样自动跳转到登录页。
找不到相关文档,尝试写自定义中间件,但卡在无法判断请求路径对应的视图是否带有该装饰器。优先想找库内置的解决方案,也接受其他可行方案。
配置代码(settings.py)
from ms_identity_web.configuration import AADConfig from ms_identity_web import IdentityWebPython AAD_CONFIG = AADConfig.parse_json(file_path='aad.config.json') MS_IDENTITY_WEB = IdentityWebPython(AAD_CONFIG) ERROR_TEMPLATE = 'auth/{}.html'
视图代码
ms_identity_web = settings.MS_IDENTITY_WEB @ms_identity_web.login_required def view_data(request): context = { 'data': 'test' } return render(request, 'data_management/view_data.html', context)
自定义中间件代码
from django.shortcuts import redirect from django.urls import reverse from django.conf import settings from django.urls import resolve ms_identity_web = settings.MS_IDENTITY_WEB class MsLoginUrlMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): if resolve(request.path).url_name == 'view_data': # 这里应该判断视图是否带装饰器 print('view data url found') if request.identity_context_data.authenticated is False: print('step 1:login required:') if request.path.startswith('/auth/sign_in') is False: print('step 2: auth required, sending to login page..') return redirect('/auth/sign_in') else: print('user should log in now..') return self.get_response(request) return self.get_response(request)
解决方案
方案1:自定义装饰器替换原装饰器(推荐)
ms_identity_web的login_required默认返回401,我们可以自己包装一层,实现跳转逻辑:
from django.shortcuts import redirect def aad_login_required(view_func): def wrapper(request, *args, **kwargs): if not request.identity_context_data.authenticated: # 跳转到库自带的登录路径 return redirect('/auth/sign_in') return view_func(request, *args, **kwargs) return wrapper
之后把视图里的@ms_identity_web.login_required替换成@aad_login_required即可。
方案2:批量配置受保护路径的中间件
在settings里定义需要保护的路径列表:
# settings.py PROTECTED_PATHS = ['/view-data/', '/admin/'] # 替换成你的实际路径
然后修改中间件,批量检查路径:
class MsLoginUrlMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): for path in settings.PROTECTED_PATHS: if request.path.startswith(path): if not request.identity_context_data.authenticated: if not request.path.startswith('/auth/sign_in'): return redirect('/auth/sign_in') break return self.get_response(request)
方案3:利用错误模板自动跳转
你已经配置了ERROR_TEMPLATE = 'auth/{}.html',直接创建auth/401.html模板,添加自动跳转逻辑:
<!-- auth/401.html --> <!DOCTYPE html> <html> <head> <meta http-equiv="refresh" content="0; url=/auth/sign_in"> </head> <body> 未登录,正在跳转至登录页面... </body> </html>
这样返回401时会渲染该模板,自动跳转到登录页。
内容的提问来源于stack exchange,提问作者jdenboer
相关产品推荐
相关产品推荐

