Keep Session Across Page Reload In Backbone JS

2020-05-24 17:37发布

问题:

I am consuming an API which returns no cookie on login,but only an auth_token as part of json response.

The base URL delivers the backbonejs application. say http://www.webiyo.com/ and by default login page is displayed.

I want to keep the user session even if the user refreshes the page in backbonejs app.

Problem is that my API doesn't return session cookie aka auth_token cookie ( it just returns an auth_token in a response json which is needed to be passed on all the subsequent calls in the query string )

So in such situation could I set a javascript cookie on my own to track user session at browser side using backbonejs ? if yes how ?

I have been referring

http://whatcodecraves.com/articles/2012/01/11/backbonejs-sessions-and-authentication but it assumes the http cookie "auth_token" is sent directly from the server to browser on login success unlike my case where the the "auth_token" is the part of the json response on logn success.

回答1:

Based on what you've described, storing the auth_token in browser's session cookie seems to be the way to go.

Backbone.js doesn't support cookie manipulation. However, you can use a jQuery plugin/write your own cookie manipulator to handle this.

Assuming you're using jquery-cookie (https://github.com/carhartl/jquery-cookie), here's an example on how you can achieve this (It's on their Wiki too!):

$.cookie('auth_token', authTokenValue);

For the API you interact with, depends on how they accept the auth_token, you may need to create a BaseModel on top of Backbone.Model to handle the use of auth_token automatically.

For example, if the API expects you to pass the auth_token as a part of QueryString, you'll need to override Backbone.Model.url() function:

var BaseModel = Backbone.Model.extend({
url: function() {
        var base = _.result(this, 'urlRoot') || _.result(this.collection, 'url') || urlError();
        if (this.isNew()) return base + '?' + $.cookie('auth_token');
        return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id) + '?' + $.cookie('auth_token');
    }
});

var EntityModel = BaseModel.extend({ ... });

So, how you override the Backbone.Model depends on what the API endpoint expects.

If following this is what your ultimate goal is, there are couple things you can do:

App.Models.Session = Backbone.Model.extend
  defaults:
    access_token: null,
    user_id: null

  initialize: ->
    @load()

  authenticated: ->
    Boolean(@get("auth_token"))

  login: (email, password, options)->
    # make an AJAX call to the authentication API
    # once returned, call @save(...) with auth_token that you got back.
    # options is there to facilitate that, if you want to pass in an onAuthencated or onNotAuthenticated callbacks, you can.

  # Saves session information to cookie
  save: (auth_token)->
    $.cookie('auth_token', auth_token)

  # Loads session information from cookie
  load: ->
    @set
      access_token: $.cookie('auth_token')

App.start = ->
  @session = new App.Models.Session()
  if @session.authenticated()
    # redirect to user page
  else
    # launch a login form
    # call @session.login(email, password)

As a side note, instead of using the option param in @login(email, password, options), you can also trigger an event, like @trigger('authenticated') from the model, letting the View/App knows that the user is now authenticated.