当前位置: 动力学知识库 > 问答 > 编程问答 >

angularjs - angular/node with passport: passport says android is not authenticated, but browser works fine

问题描述:

So this is pretty weird.

I am running an app with angular, node and passport.

It's managing some information and you can view a video associated with it.

When I use the app in the browser, all seems to work fine. But when I access the app with an android phone browser (didn't test with iOS), I can login and all works fine, but when I access the video (in the same session!) passport denies access! I am baffled as the rest of the application works fine in the android browser...

routes:

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()

)

play the video:

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)

)

The output when accessing with the android browser is:

no range

Not authenticated!

EDIT: If I remove the passport authentication, the video can be displayed on the phone...

EDIT2: on request: the serialize functions

passport.serializeUser((user, done) ->

done(null, user._id)

)

passport.deserializeUser((id, done) ->

User.findById(id, (err, user) ->

done(err, user)

)

)

So it seems the code runs fine, the video gets loaded and returned to the browser, but it cannot play it for whatever weird reason which is pretty puzzling for me...

In a normal desktop browser (e.g. Chrome), I get a range in the headers, then the video returns and it gets played - no "Not authenticated!" message!

网友答案:

the potential problem could be here:

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

res.end(data)

We are telling the header here that we send a chunk, but are actually sending the whole file...

From here I found the way to do that correctly:

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

This seems to improve things a lot but we'll need to check further

分享给朋友:
您可能感兴趣的文章:
随机阅读: