1

我按照 django doc 的建议实现了一个自定义身份验证后端,我有两种方法 - 身份验证和 get_user。

我确认调用了我的自定义“身份验证”方法并返回了正确的用户,但在 request.user 中我总是得到 AnonymousUser 并且我的“get_user”方法永远不会被调用。

它可能与会话有关,因为当我解码会话时,我看到的唯一东西是"{u'django_language': u'en'}"

我错过了什么?

这是我的自定义 SSOBackend

class SSOBackend(object):
    """
    My authentication backend
    """

    def authenticate(self, *args, **kwargs):
        """
        Authenticate user using access_token and refresh_token
        """

        access_token = kwargs.get('access_token')
        refresh_token = kwargs.get('refresh_token')
        user_info = _get_user_info(access_token, refresh_token)
        try:
            user = User.objects.get(username=user_info['user_id'])
        except User.DoesNotExist:
            import uuid
            random_password = uuid.uuid4()
            user = User(username=user_info['user_id'], password=random_password)
            user.save()

        return user


    # Required for your backend to work properly - unchanged in most scenarios
    def get_user(self, user_id):
        try:
            logger.info("SSOBackend.get_user:  User_id = %s" %user_id)
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

我正在使用我的自定义中间件登录用户:

class SSOMiddleware(object):

    def process_view(self, request, view_func, view_args, view_kwargs):

        if 'state' in request.GET and 'code' in request.GET and '/auth-callback/' in request.get_full_path():

            redirect_uri = "http://{domain}/sso/auth-callback/".format(domain=request.get_host())
            next_page = "/"

            
            code = request.GET['code']

            # where to redirect after successful authentication
            next_page = request.GET['state']

            config = SSOConfig()
            token_url = config.token_url
            client_id = config.client_id
            client_secret = config.client_secret

            # retrieve access token using code
            headers = {"content-type": "application/x-www-form-urlencoded", "host": "www.myproject.com"}
            payload = ("grant_type=authorization_code&code={code}&client_id={client_id}&"
                        "client_secret={client_secret}&redirect_uri={redirect_uri}").format(**locals())

            response = requests.post(token_url, data=payload, headers=headers)

            if response.status_code != 200:
                return HttpResponseBadRequest(_("Bad Request"))

            authorization_info = response.json()

            access_token = authorization_info["access_token"]
            refresh_token = authorization_info["refresh_token"]
            authenticate(access_token=access_token, refresh_token=refresh_token)

            return HttpResponseRedirect(next_page)
 
        return None

这是我的 settings.py 中的内容:

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'myproject.sso.middleware.SSOMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.locale.LocaleMiddleware',
)

AUTHENTICATION_BACKENDS = (
    'myproject.sso.backends.SSOBackend',
    'django.contrib.auth.backends.ModelBackend',
)
4

1 回答 1

0

代表问题作者回答:

我想通了。在对用户进行身份验证后,我错过了这些行:

from django.contrib.auth import authenticate, login

....

user = authenticate(access_token=access_token, refresh_token=refresh_token)

if user is not None:
    login(request, user)
于 2021-09-01T03:18:34.417 回答