将对象从服务器拦截器传送到函数中

2024-04-25 12:01:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我创建了一个简单的服务器拦截器,它基于JWT令牌检索用户。在

但现在我想把它提供给我所有的服务方法。在

目前我用的是装饰工。但我想避免所有的方法都要修饰。以防万一,只装饰那些不需要用户的。在

有人能给我个线索吗?在

这是我的代码:

class AuthInterceptor(grpc.ServerInterceptor):
"""Authorization Interceptor"""

def __init__(self, loader):
    self._loader = loader

def intercept_service(self, continuation, handler_call_details):
    # Authenticate if we not requesting token.
    if not handler_call_details.method.endswith('GetToken'):
        # My Authentication class.
        auth = EosJWTAuth()
        # Authenticate using the headers tokens to get the user.
        user = auth.authenticate(
            dict(handler_call_details.invocation_metadata))[0]

        # Do something here to pass the authenticated user to the functions.

    cont = continuation(handler_call_details)
    return cont

我希望我的方法可以像这样访问用户。在

^{pr2}$

Tags: theto方法用户selfdef装饰loader
1条回答
网友
1楼 · 发布于 2024-04-25 12:01:58

这是web服务器的常见需求,向处理程序中添加decorator以显式地设置身份验证/授权需求是一个好主意。它有助于提高可读性,并降低总体复杂性。在

不过,这里有一个解决问题的方法。它使用Python元类自动修饰每个服务程序方法。在

import grpc
import functools
import six

def auth_decorator(func):
    @functools.wraps(func)
    def wrapper(request, context):
        if not func.__name__.endswith('GetToken'):
            auth = FooAuthClass()
            try:
                user = auth.authenticate(
                    dict(context.invocation_metadata)
                )[0]
                request.user = user
            except UserNotFound:
                context.abort(
                    grpc.StatusCode.UNAUTHENTICATED,
                    'Permission denied.',
                )
        return func(request, context)

    return wrapper

class AuthMeta:

    def __new__(self, class_name, bases, namespace):
        for key, value in list(namespace.items()):
            if callable(value):
                namespace[key] = auth_decorator(value)
        return type.__new__(self, class_name, bases, namespace)

class BusinessServer(FooServicer, six.with_metaclass(AuthMeta)):

    def LogicA(self, request, context):
        # request.user accessible
        ...

    def LogicGetToken(self, request, context):
        # request.user not accessible
        ...

相关问题 更多 >