前端文章翻译

Cookies vs Token,在AngularJS中使用正确

2016-07-19  本文已影响2362人  mervynyang

介绍

对于前端和api调用而言,Cookies和Tokens是两种服务器端基本的验证方式。

Cookies对比Token

这是Cookies和Tokens工作方式的图解

图解

使用Token的好处是什么呢?

什么是JSON Web Token?JSON Web Token是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。

实现

假设你有一个node.js的应用,下面你可以找到这个架构的组件。

服务端

让我们开始安装express-jwt和jsonwebtoken:

    $ npm install express-jwt jsonwebtoken

定义一个express中间件保护每一次/api的调用。

    var expressJwt = require('express-jwt');
    var jwt = require('jsonwebtoken');

    // We are going to protect /api routes with JWT
    app.use('/api', expressJwt({secret: secret}));

    app.use(express.json());
    app.use(express.urlencoded());

这是一个angular的应用,将会带上用户的凭证通过ajax去执行post请求。

    app.post('/authenticate', function (req, res) {
      //TODO validate req.body.username and req.body.password
      //if is invalid, return 401
      if (!(req.body.username === 'john.doe' && req.body.password === 'foobar')) {
        res.send(401, 'Wrong user or password');
        return;
      }

      var profile = {
        first_name: 'John',
        last_name: 'Doe',
        email: 'john@doe.com',
        id: 123
      };

      // We are sending the profile inside the token
      var token = jwt.sign(profile, secret, { expiresInMinutes: 60*5 });

      res.json({ token: token });
    });

直接获取到名字为/api/restricted的资源。注意凭证的验证在expressJwt中间件执行。

    app.get('/api/restricted', function (req, res) {
      console.log('user ' + req.user.email + ' is calling /api/restricted');
      res.json({
        name: 'foo'
      });
    });

AngularJS端

第一步,在客户端使用AngularJS取得 JWT Token。为了得到我们需要的用户凭证,我们得先创建一个表单的视图,能够让用户输入用户名和密码。

    <div ng-controller="UserCtrl">
      <span></span>
      <form ng-submit="submit()">
        <input ng-model="user.username" type="text" name="user" placeholder="Username" />
        <input ng-model="user.password" type="password" name="pass" placeholder="Password" />
        <input type="submit" value="Login" />
      </form>
    </div>

一个处理表单提交的controller:

    myApp.controller('UserCtrl', function ($scope, $http, $window) {
      $scope.user = {username: 'john.doe', password: 'foobar'};
      $scope.message = '';
      $scope.submit = function () {
        $http
          .post('/authenticate', $scope.user)
          .success(function (data, status, headers, config) {
            $window.sessionStorage.token = data.token;
            $scope.message = 'Welcome';
          })
          .error(function (data, status, headers, config) {
            // Erase the token if the user fails to log in
            delete $window.sessionStorage.token;

            // Handle login errors here
            $scope.message = 'Error: Invalid user or password';
          });
      };
    });

现在我们JWT保存到sessionStorage中,如果token设置了,我们将在每一次使用$http请求的时候设置Authorization。作为请求头的一部分值,我们将使用Bearer<token>

sessionStorage: 尽管不支持所有的浏览器,但是你可以使用polyfill,它是代替cookies的一个比较好的方案。

($cookies, $cookieStore)以及localStorage:在用户关闭浏览器标签之后数据依然还会存在。

    myApp.factory('authInterceptor', function ($rootScope, $q, $window) {
      return {
        request: function (config) {
          config.headers = config.headers || {};
          if ($window.sessionStorage.token) {
            config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
          }
          return config;
        },
        response: function (response) {
          if (response.status === 401) {
            // handle the case where the user is not authenticated
          }
          return response || $q.when(response);
        }
      };
    });

    myApp.config(function ($httpProvider) {
      $httpProvider.interceptors.push('authInterceptor');
    });

然后,我们发送一个请求到/api/restricted

    $http({url: '/api/restricted', method: 'GET'})
    .success(function (data, status, headers, config) {
      console.log(data.name); // Should log 'foo'
    });

服务器端控制台:

    user foo@bar.com is calling /api/restricted

原文: angularjs-authentication-with-cookies-vs-token

上一篇 下一篇

猜你喜欢

热点阅读