vue 无法获得access-token

技术问题 · johocn · 于 4年前 发布 · 2606 次阅读

第一步vue开发配置

module.exports = {
  devServer:{
    host: 'localhost',
    port: 8080,
    https: false,
    open: true,
    proxy: {
      '/api': {
        target: 'http://appserver.fecshoptest.com',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
}

第二步 axios拦截器

// 引用API文件
import api from './config/api'
Vue.prototype.$http = axios
Vue.prototype.qs = qs
// Vue.prototype.store = store
// 添加一个请求拦截器
// sessionStorage.setItem('access_token', 'lycovV39qrJUW5vsKs58vVQa30EcQESZ')
axios.interceptors.request.use(
  config => {
    config.baseURL = '/api'
    // config.baseURL = 'http://appserver.fecshoptest.com'
    config.withCredentials = true // 允许携带token ,这个是解决跨域产生的相关问题
    config.timeout = 6000
    const token = sessionStorage.getItem('access_token')
    // const token = store.state.token
    console.log('++请求查询本地保存++access_token++' + sessionStorage.getItem('access_token'))
    console.log('++请求查询保存的++stortoken' + store.state.token)
    // const csrf = store.getters.csrf
    if (token) {
      config.headers = {
        'access-token': token,
        'Content-Type': 'application/x-www-form-urlencoded',
        'fecshop-currency': 'USD',
        'fecshop-lang': 'zh'
      }
    }
    if (config.url === 'refresh') {
      config.headers = {
        'refresh-token': sessionStorage.getItem('refresh_token'),
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    }
    // 参数格式转换
    if (config.method === 'post') {
      config.data = qs.stringify(config.data)
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)
// 在 response 拦截器实现
axios.interceptors.response.use(
  response => {
    console.log('++返回时本地保存的++access_token++' + sessionStorage.getItem('access_token'))
    console.log('++返回时本地保存的++stortoken' + store.state.token)
    console.log('++返回时头部的accesstoken++' + response.headers['access-token'])
    if (response.data.code === 200) {
      sessionStorage.setItem('access_token', response.headers['access-token'])
      store.commit('setToken', response.headers['access-token'])
    }
    console.log('++返回后第二次确认本地保存的++access_token++' + sessionStorage.getItem('access_token'))
    console.log('++返回后第二次确认+stortoken' + store.state.token)
    return response
  },
  error => {
    return Promise.reject(error)
  }
)

操作结果 第一次登录请求 从http://localhost:8080/#/login post请求 /customer/login/account登录成功 返回结果如下

++请求查询本地保存++access_token++null
main.js?56d7:26 ++请求查询保存的++stortokenundefined
main.js?56d7:55 ++返回时本地保存的++access_token++null
main.js?56d7:56 ++返回时本地保存的++stortokenundefined
main.js?56d7:57 ++返回时头部的accesstoken++I3y77YP9Gz_HwHWgq94dsGA3C3tYJEvA
main.js?56d7:62 ++返回后第二次确认本地保存的++access_token++I3y77YP9Gz_HwHWgq94dsGA3C3tYJEvA
main.js?56d7:63 ++返回后第二次确认+stortokenI3y77YP9Gz_HwHWgq94dsGA3C3tYJEvA

一切正常,返回时头部的accesstoken++I3y77YP9Gz_HwHWgq94dsGA3C3tYJEvA

第二次从http://localhost:8080/#/table get请求 /cms/home/index
返回的结果如下,查询结果也是正确的

++请求查询本地保存++access_token++I3y77YP9Gz_HwHWgq94dsGA3C3tYJEvA
main.js?56d7:26 ++请求查询保存的++stortokenI3y77YP9Gz_HwHWgq94dsGA3C3tYJEvA
main.js?56d7:55 ++返回时本地保存的++access_token++I3y77YP9Gz_HwHWgq94dsGA3C3tYJEvA
main.js?56d7:56 ++返回时本地保存的++stortokenI3y77YP9Gz_HwHWgq94dsGA3C3tYJEvA
main.js?56d7:57 ++返回时头部的accesstoken++undefined
main.js?56d7:62 ++返回后第二次确认本地保存的++access_token++undefined
main.js?56d7:63 ++返回后第二次确认+stortokenundefined

问题出现在这里 返回时头部的accesstoken++undefined

也就是第二次查询时返回的头部信息中没access-token 就是这个语句,response.headers['access-token']没有被定义,请问这个问题要从那里入手解决

共收到 2 条回复
johocn#14年前 0 个赞

二次查询 response.headers的 信息如下 第一次

access-control-allow-credentials
:
"true"
access-control-allow-origin
:
"http://localhost:8080"
access-control-expose-headers
:
"Origin, X-Requested-With, Content-Type, Accept, fecshop-uuid, fecshop-lang, fecshop-currency, access-token"
access-token
:
"Ghm9FdNFoJcuOPv7QC07ezGo1165XmEH"
connection
:
"close"
content-type
:
"application/json; charset=UTF-8"
date
:
"Mon, 24 Feb 2020 15:37:11 GMT"
fecshop-currency
:
"USD"
server
:
"Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02"
transfer-encoding
:
"chunked"
vary
:
"Accept"
x-debug-duration
:
"80"
x-debug-link
:
"/debug/default/view?tag=5e53eda7e1ab9"
x-debug-tag
:
"5e53eda7e1ab9"
x-powered-by
:
"PHP/7.3.4"

第二次

access-control-allow-credentials
:
"true"
access-control-allow-origin
:
"http://localhost:8080"
access-control-expose-headers
:
"Origin, X-Requested-With, Content-Type, Accept, fecshop-uuid, fecshop-lang, fecshop-currency, access-token"
connection
:
"close"
content-type
:
"application/json; charset=UTF-8"
date
:
"Mon, 24 Feb 2020 15:37:12 GMT"
fecshop-currency
:
"USD"
server
:
"Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02"
transfer-encoding
:
"chunked"
vary
:
"Accept"
x-debug-duration
:
"65"
x-debug-link
:
"/debug/default/view?tag=5e53eda809385"
x-debug-tag
:
"5e53eda809385"
x-powered-by
:
"PHP/7.3.4"
Fecmall#24年前 0 个赞

1.access_token是登陆后才会有的,这个是用来标记登陆状态, 登陆用户操作会返回access_token,

2.登陆用户,生成access_token,写入response header 返回

https://github.com/fecshop/yii2_fecshop/blob/master/services/Customer.php#L795

$this->setHeaderAccessToken($identity->access_token);

https://github.com/fecshop/yii2_fecshop/blob/master/services/Customer.php#L878

 protected function actionSetHeaderAccessToken($accessToken)
    {
        if ($accessToken) {
            Yii::$app->response->getHeaders()->set('access-token', $accessToken);
            return true;
        }
    }

在用户登陆后就会返回access_token,从header获取

3.access_token的验证

https://github.com/fecshop/yii2_fecshop/blob/master/app/appserver/modules/AppserverTokenController.php#L57

$behaviors['authenticator'] = [  
            'class' => CompositeAuth::className(),  
            'authMethods' => [  
                # 下面是三种验证access_token方式  
                //HttpBasicAuth::className(),  
                //HttpBearerAuth::className(),  
                # 这是GET参数验证的方式  
                # http://10.10.10.252:600/user/index/index?access-token=xxxxxxxxxxxxxxxxxxxx  
                QueryParamAuth::className(),  
            ],  
          
        ];  

https://github.com/fecshop/yii2_fecshop/blob/master/yii/filters/auth/QueryParamAuth.php#L27

 public function authenticate($user, $request, $response)
    {   
        $identity = Yii::$service->customer->loginByAccessToken(get_class($this));
        if($identity){
            return $identity;
        }else{
            $cors = Yii::$service->helper->appserver->getYiiAuthCors();
            if (is_array($cors)) {
                foreach ($cors as $c) {
                    header($c);
                }
            }
            $code = Yii::$service->helper->appserver->account_no_login_or_login_token_timeout;
            $result = [ 'code' => $code,'message' => 'token is time out'];
            Yii::$app->response->data = $result;
            Yii::$app->response->send();
            Yii::$app->end();
        }
    }

https://github.com/fecshop/yii2_fecshop/blob/master/services/Customer.php#L808

/**
     * Logs in a user by the given access token.
     * Token is passed through headers. So you can get it from the key 'access-token'.
     * @param $type
     * @return IdentityInterface|null the identity associated with the given access token. Null is returned if
     * the access token is invalid.
     * @see [[\yii\web\User::loginByAccessToken()]]
     */
    protected function actionLoginByAccessToken($type = null)
    {
        $header = Yii::$app->request->getHeaders();
        if (isset($header['access-token']) && $header['access-token']) {
            $accessToken = $header['access-token'];
        } else {
            return null;
        }

        /** @var \fecshop\models\mysqldb\Customer|null $identity */
        $identity = Yii::$app->user->loginByAccessToken($accessToken, $type);
        if ($identity !== null) {
            $access_token_created_at = $identity->access_token_created_at;
            $timeout = Yii::$service->session->timeout;
            // 如果时间没有过期,则返回 identity
            if ($access_token_created_at + $timeout > time()) {
                // 如果时间没有过期,但是快要过期了,在过$updateTimeLimit段时间就要过期,那么更新access_token_created_at。
                $updateTimeLimit = Yii::$service->session->updateTimeLimit;
                if ($access_token_created_at + $timeout <= (time() + $updateTimeLimit)) {
                    $identity->access_token_created_at = time();
                    $identity->save();
                }
                return $identity;
            } else {
                $this->logoutByAccessToken();
                return null;
            }
        }
        return null;
    }
添加回复 (需要登录)
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册
Your Site Analytics