webman 获取用户ip的建议

小阳光

~~ webman中
$request->getRemoteIp()取的是真实tcp连接 ip
如有代理 nginx 就不友好,不管头怎么设置真实ip都是nginx的真实ip
自己实现获取用户ip虽不难,但是,建议加入到 request 类里面
$request->header('X-Real-IP')~~

3740 3 0
3个回答

walkor

更新下 webman-framework 到1.0.2或者后续的更高版本,使用 $request->getRealIp(); 方法获取真实ip。

  • 小阳光 2020-09-01

    还有一个建议,就是在控制器里面添加一个初始化方法,如果存在此方法,每个请求进来都会调用一下,此方法。

小阳光

首先说明我为什么需要初始化函数,在我们的业务中我想,在中间件鉴权,鉴权后给控制器赋值当前用户的id及信息,当然,这里也可以赋值给request 对象的属性,但是我们习惯在 控制器里面$this->user_id,所以想在控制器每个请求进来就初始化的时候赋值用户id,但是初始化要在中间件后,下面是我修改的框架源代码,大家帮忙看看,有没有什么bug。

protected static function getCallback($app, $call, $args = null, $with_global_middleware = true)
    {
        $args = $args === null ? null : \array_values($args);
        $middleware = Middleware::getMiddleware($app, $with_global_middleware);
        if ($middleware) {
            $callback = array_reduce($middleware, function ($carry, $pipe) {
                return function ($request) use ($carry, $pipe) {
                    return $pipe($request, $carry);
                };
            }, function ($request) use ($call, $args) {
                self::_initialize($request);  //在调用控制器回调前 调用初始化函数
                if ($args === null) {
                    $response = $call($request);
                } else {
                    $response = $call($request, ...$args);
                }
                if (\is_scalar($response) || null === $response) {
                    $response = new Response(200, [], $response);
                }
                return $response;
            });
        } else {
            self::_initialize($request);   //没有中间件的时候
            if ($args === null) {
                $callback = $call;
            } else {
                $callback = function ($request) use ($call, $args) {
                    return $call($request, ...$args);
                };
            }
        }
        return $callback;
    }
```
    /**
 * 控制器初始化
 * @param string $request
 */
private static function _initialize($request)
{
    if ($request->controller) {
        $controller_obj = static::$_container->get($request->controller);
        if (method_exists($controller_obj, '_initialize')) {
            $_initialize = [$controller_obj, '_initialize'];
            $_initialize($request);
        }
    }
}
```
  • 暂无评论
walkor

代码看着没什么问题。

不过鉴权更适合用中间件,大部分框架都是用中间件来鉴权的,这样可以控制业务流程流转,比如在鉴权失败时统一跳转到登录页面,如果在你说的那个控制器初始化函数里做就很难做到。

另外用 $request->user_id$控制器->user_id 更合理一些。$request类似用户输入的变量,包含请求数据,用户鉴权数据。控制器是公共的方法,只根据输入变量$request来处理业务,控制器自身不应该存储用户状态数据。控制器是单例的多请求共享的,也就是说上一个请求设置的$控制器->user_id,下一个请求没有将$控制器->user_id重置直接使用将得到错误的用户数据。

  • 小阳光 2020-09-02

    你说的我也明白,我的意思是,鉴权还是在中间件里面做,但是每个请求通过中间件后,在调用控制器方法前,调用一下控制器对象的特定方法(比如_initialize)。我们需要在这里做一些事情。比如清除一些数据,比如修改当前对象的一些值。可能只是我们有这个需求,cv代码的时候改动少。

年代过于久远,无法发表回答
🔝