V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
linkbg
V2EX  ›  PHP

Laravel+Vue 前后端分离

  •  
  •   linkbg · 2017-02-22 12:30:13 +08:00 · 12492 次点击
    这是一个创建于 2630 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前实践一个项目。有些小问题。可能想法错了,还望大家指点一下。 目录结构:

    ---vue-laravel
      |
      | ---- client #这是纯的 vue 目录
      | ---- server #laravel 放在这里
    

    laravel 提供 api 并且通过 CORS 解决跨域的问题。

    目前认证这块是正常的。

    但是我想把注册的模块也通过 vue 来实现页面展示, laravel 来存入数据库。但是,我使用 CORS 来提交数据会报 422 的错误。好像应该我没有把 CSRF 值传入的问题。

    代码如下: vue 提交注册数据

    handleRegisterFormSubmit () {
            const postData = {
              grant_type: 'client_credentials',
              client_id: clientId,
              client_secret: clientSecret,
              email: this.register.email,
              password: this.register.password,
              password_confirmation: this.register.password_confirmation,
              name: this.register.name,
              scope: ''
            }
            this.$http.post('http://localhost:8000/api/register', postData)
              .then(response => {
                console.log(response)
              })
          }
    
    

    laravel Api 路由:

    Route::post('/register',"Auth\RegisterController@register");
    
    

    请问应该怎么来处理这种没有认证之前的前后端数据交互呢?谢谢

    第 1 条附言  ·  2017-02-22 14:31:57 +08:00
      this.$http.post(loginUrl, postData)
              .then(response => {
    //   设置客户端认证
                if (response.status === 200) {
                  console.log(response)
                  clientAuth.access_token = response.data.access_token
                  window.localStorage.setItem('clientAuth', JSON.stringify(clientAuth))
                }
    // 携带客户端认证信息和要post的数据
                this.$http.post('http://127.0.0.1:8000/api/register',
                  postDataRegister, {headers: getHeaderClient()})
                  .then(response => {
                    console.log(response)
                  })
              })
    
    

    header

    
    export const getHeaderClient = function () {
      const tokenData = JSON.parse(window.localStorage.getItem('clientAuth'))
      const headers = {
        'Accept': 'application/json',
        'Authorization': 'Bearer ' + tokenData.access_token,
      }
    
      return headers
    }
    
    

    客户端认证成功,但是提交数据就401

    第 2 条附言  ·  2017-02-22 21:22:23 +08:00

    经过一下午反复思考,最终还是决绝了。但是如果laravel中register的validator如果出现,比如两个密码不一致或者密码长度小于6,反者就是这个验证过不了就会出现 422 (Unprocessable Entity)的错误。这一块准备在前端这边进行一个判断然后再post请求。

    code如下:

        methods: {
          handleRegisterFormSubmit () {
            const postData = {
              grant_type: 'client_credentials',
              client_id: clientId,
              client_secret: clientSecret,
              scope: ''
            }
            const postDataRegister = {
              grant_type: 'client_credentials',
              client_id: clientId,
              client_secret: clientSecret,
              email: this.register.email,
              password: this.register.password,
              password_confirmation: this.register.password_confirmation,
              name: this.register.name,
              scope: ''
            }
            const clientAuth = {}
            this.$http.post(loginUrl, postData) // 获取客户端认证
              .then(response => {
                if (response.status === 200) {
                  console.log(response)
                  clientAuth.access_token = response.data.access_token
                  window.localStorage.setItem('clientAuth', JSON.stringify(clientAuth)) // 本地存储认证信息
                }
                this.$http.post('http://127.0.0.1:8000/api/register',
                  postDataRegister, {headers: getHeaderClient()})
                  .then(response => {
                    console.log(response) // post请求创建
                  })
              })
          }
    
        }
    

    一些常量:

    export const apiDomain = 'http://localhost:8000/'
    export const loginUrl = apiDomain + 'oauth/token'
    export const userUrl = apiDomain + 'api/user'
    

    总算解决了。

    21 条回复    2017-02-23 08:51:40 +08:00
    airycanon
        1
    airycanon  
       2017-02-22 12:41:09 +08:00   ❤️ 1
    Laravel 5.4 里面用的是 axios 发请求,原理如下:

    把变量传到页面中:
    ```
    <script>
    window.Laravel = {!! json_encode([
    'csrfToken' => csrf_token(),
    ]) !!};
    </script>
    ```
    在 axios 的 header 中设置 csrfToken :
    ```window.axios.defaults.headers.common = {
    'X-CSRF-TOKEN': window.Laravel.csrfToken,
    'X-Requested-With': 'XMLHttpRequest'
    };
    ```
    用 Vue 的话同理。
    airycanon
        2
    airycanon  
       2017-02-22 12:51:36 +08:00
    不好意思,没看清是前后端分离,这样的话我只知道设置 CSRF 中间件的 $except ,可以排除掉某些路由,或者直接在 Http\Kernel.php 中禁用 CSRF 中间件了。
    branchzero
        3
    branchzero  
       2017-02-22 12:57:37 +08:00   ❤️ 1
    你确定走了 api 的 middleware 了么,如果走 api 的 middleware 的话默认是不会启用 csrf check 的
    linkbg
        4
    linkbg  
    OP
       2017-02-22 14:28:50 +08:00
    @branchzero 谢谢。但是新的问题是 401 但是我明明已经取得客户端授权了。请问这个怎么解决呢?我将新的情况补充在问题上。
    ydxred
        5
    ydxred  
       2017-02-22 14:32:40 +08:00
    分离不是应该写在视图里面吗?
    linkbg
        6
    linkbg  
    OP
       2017-02-22 14:39:56 +08:00 via iPhone
    @ydxred 视图这里完全交给 vue 。 laravel 的视图就不去写了。
    coooooooode
        7
    coooooooode  
       2017-02-22 15:49:48 +08:00
    和我想的一样,前端就只做前端的事,让 vue 控制数据与 api 调用。 支持!
    jellybool
        8
    jellybool  
       2017-02-22 16:11:59 +08:00
    我觉得你阔以看看这个
    jellybool
        9
    jellybool  
       2017-02-22 16:12:37 +08:00   ❤️ 1
    benbenlang
        10
    benbenlang  
       2017-02-22 18:15:56 +08:00
    @jellybool 你的视频要付费啊,,,
    jellybool
        11
    jellybool  
       2017-02-22 19:03:48 +08:00
    @benbenlang 是的
    skyjerry
        12
    skyjerry  
       2017-02-22 19:16:54 +08:00 via iPhone
    @jellybool 出示学生证可否优惠?学生,没什么钱
    jellybool
        13
    jellybool  
       2017-02-22 19:24:16 +08:00
    @skyjerry 这个暂时没有,不好意思
    linkbg
        14
    linkbg  
    OP
       2017-02-22 21:31:22 +08:00
    @jellybool 价格有点小贵了。但是能分享一下,您是这样写的吗?我新的附言。
    sobigfish
        15
    sobigfish  
       2017-02-22 21:31:39 +08:00
    linoder
        16
    linoder  
       2017-02-22 22:01:43 +08:00
    都分离了 csrf 还有用么?
    linkbg
        17
    linkbg  
    OP
       2017-02-22 22:15:41 +08:00
    scrf 没有用了。是传入 access_token 。
    linkbg
        18
    linkbg  
    OP
       2017-02-22 22:16:00 +08:00
    scrf 没有用了。是传入 access_token 。

    @linoder
    yangqi
        19
    yangqi  
       2017-02-22 22:45:00 +08:00
    都前后端分离了,直接把 csrf 的 middleware 关掉就行了
    crossmaya
        20
    crossmaya  
       2017-02-23 04:04:33 +08:00
    一看就是 auth 中间件的问题!
    chaegumi
        21
    chaegumi  
       2017-02-23 08:51:40 +08:00
    为什么没人说
    client_id: clientId,
    client_secret: clientSecret,
    同时存在在 js 代码中,是否有问题。限制该 client_id 只能使用特定的 grant_type ?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4406 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 05:33 · PVG 13:33 · LAX 22:33 · JFK 01:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.