带护照的角度/节点:护照说android没有经过身份验证,但浏览器工作正常

时间:2014-08-20 15:10:37

标签: android angularjs node.js video passport.js

所以这很奇怪。

我正在运行带有角度,节点和护照的应用程序。 它管理一些信息,您可以查看与之相关的视频。

当我在浏览器中使用该应用程序时,一切似乎都正常。但是当我使用Android手机浏览器访问应用程序(没有用iOS测试)时,我可以登录并且一切正常,但是当我访问视频时(在同一个会话中!),护照拒绝访问!我很困惑,因为其他应用程序在Android浏览器中工作正常......

路线:

app.all('*',ensureAuthenticated)

app.get('/ping', routes.ping)
app.get('/logout', routes.logout)
app.get('/start', routes.start)
#more routes
app.get('/videos/:name', can_view_video, media.play) #can_view_video checks if a user has the rights to see the video

#Middleware to check that a user is authenticated
ensureAuthenticated = (req, res, next) ->
      if (req.isAuthenticated())
          return next()
      logger.debug("Not authenticated!")
      res.redirect('/')

#Middleware to check that user can view video
can_view_video = (req, res, next) ->
    url = req.url
    url_params_only = url.substring("/videos/".length)
    id = url_params_only.substring(0, url_params_only.indexOf("/"))
    can_access(req, res, id, (err) ->
      if err?
        handle_error(err, err.message, res)
      else
        return next()
    )

can_access = (req, res, id=null, next) ->
  role = req.user.role
  if id is null
    id = req.params.userId
  user_id = req.user.id
  User.findOne({ user_id:id }, (err, user) ->
    if err?
      handle_error(err, err.message, res)
    if not user?
      text = "no user with that id"
      handle_error(err, text, res)
    else if not id == user_id or role is not "admin"
      text = "no user with that id"
      logger.debug(text)
      handler_error(new Error(text), text, res)
    else
      logger.debug "Login: can access, ok"
      next()
    )

播放视频:

exports.play = (req,res) ->
    video_path = __dirname + "/media/" + req.user.id + "/" + req.params.video

    fs.readFile(video_path, (err, data) ->
        if err?
          handle_error(err, "video can't be read", res)
        else
            range = req.headers.range
            if range?
                total = data.length

                parts = range.replace(/bytes=/, "").split("-")
                partialstart = parts[0]
                partialend = parts[1]

                start = parseInt(partialstart, 10)
                end = if partialend then parseInt(partialend, 10) else total-1

                chunksize = (end-start)+1

                res.writeHead(206, 
                    "Content-Range": "bytes " + start + "-" + end + "/" + total,
                    "Accept-Ranges": "bytes", 
                    "Content-Length": chunksize, 
                    "Content-Type": 'video/mp4' )
            else
                logger.debug("no range")
                res.writeHead(200,
                    "Content-Length": data.length,
                    "Content-Type": 'video/mp4')                
            res.end(data)
    )

使用Android浏览器访问时的输出是:

no range
Not authenticated!

编辑:如果我删除了护照身份验证,视频可以显示在手机上......

EDIT2:根据要求:序列化函数

passport.serializeUser((user, done) ->
      done(null, user._id)
)

passport.deserializeUser((id, done) ->
      User.findById(id, (err, user) ->
         done(err, user)
      )
)

所以看起来代码运行正常,视频被加载并返回到浏览器,但它无法播放任何奇怪的原因,这对我来说非常令人费解......

在普通的桌面浏览器(例如Chrome)中,我在标题中获得了一个范围,然后视频返回并播放 - 没有"未经过身份验证!"消息!

1 个答案:

答案 0 :(得分:0)

潜在的问题可能在这里:

res.writeHead(206, 
                    "Content-Range": "bytes " + start + "-" + end + "/" + total,
                    "Accept-Ranges": "bytes", 
                    "Content-Length": chunksize, 
                    "Content-Type": 'video/mp4' )
...

res.end(data)

我们在这里告诉标题我们发送了一个块,但实际上是在发送整个文件......

here我找到了正确的方法:

res.end(data.slice(start, end+1), "binary");

这似乎改善了很多事情,但我们需要进一步检查