加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

使用Angular.js和iOS客户端对Node.js应用进行身份验证

发布时间:2020-12-17 08:17:38 所属栏目:安全 来源:网络整理
导读:我试图尽可能多地阅读不同的答案和帖子,但是我仍然不能完全满足我的需求。我正在努力解决用户身份验证,登录等方面最好的(最有效率,但更安全)的方式。 我有一个Node.js服务器,在Express上运行;我有一个Angular.js网络应用程序我有一个iOS应用程序。我用Ex
我试图尽可能多地阅读不同的答案和帖子,但是我仍然不能完全满足我的需求。我正在努力解决用户身份验证,登录等方面最好的(最有效率,但更安全)的方式。

我有一个Node.js服务器,在Express上运行;我有一个Angular.js网络应用程序我有一个iOS应用程序。我用Express / Node.js公开了一个RESTful API。

饼干

我读过的第一件事就是使用cookies,并在服务器端(散列)和客户端(未分配)上存储会话ID /登录令牌。客户端将会传送每个请求的id,服务器会将其哈希,解析并相应地处理该请求。这不是RESTful(不是一个巨大的问题),但更重要的是,我必须复制我的API:一个用于用户名/密码认证(例如通过curl完成),一个用于基于cookie的身份验证(例如我的网络应用程序)?

另一个问题是:如果我有一个用户的多个连接,我会做什么,例如他们登录在两个浏览器,一个iPhone和一个iPad。我的存储的会话ids需要现在是一个数组?

HTTP基本认证

接下来的想法是使用HTTP Basic Auth(使用SSL),这似乎很简单,但不推荐,因为您需要在每个请求中传输用户名和密码。如果我使用HTTP Basic Auth进行操作,那么我会将用户名和密码存储在cookie(或HTML本地存储)中,以允许“记住我”功能吗?或者我可以组合这两个:使用HTTP Basic Auth进行实际请求(发布新的帖子等),并且只使用存储在cookie中的会话ID来初始化日志/记住我的方面?

正在传送会话ID比只传送用户密码更安全吗?怎么样?
会话ID将作为表面上的密码,因此对于我来说,它将具有与发送密码相同的安全问题。

基本认证似乎在所有平台上得到支持,这是理想的。主要的缺点似乎是需要每个请求传输客户端认证数据。有办法缓解这个问题吗?

OAuth的

OAuth似乎对我的需要是过分的。我想我将失去卷曲命令测试我的API的能力。如何将OAuth作为Cookie方法的改进?

你可能会告诉我,我有点混淆了不同的信息,所以如果你有一套良好的链接 – 适用于这种情况 – 我很想读它们。我试图找到一个适合所有平台的解决方案,但仍然尽可能安全。此外,如果我的任何术语错误,请纠正我,因为它会使我的搜索变得更容易。

谢谢。

更新:

我一直在想这个问题,我有一个想法。请告诉我,如果这是愚蠢/不安全/任何反馈,因为我不知道这是否好。

当用户登录时,我们生成一个随机会话ID(盐渍等)。该可选会话ID被发送到客户端,客户端可以存储(例如,在Cookie中)如果他们选择;会话ID存储在数据库中。

然后,可以将此会话ID作为HTTP身份验证头或查询字符串作为每个请求发送,或者客户端可以根据需要发送用户名和密码(这给我们提供了常规的REST API)。在服务器端,我们首先检查一个session id参数,如果不存在,我们检查用户名/密码。如果没有 – 错误。

在服务器上,我们检查会话ID是否与正确的用户名相关联。如果是,我们完成请求。

每次用户登录时,我们创建一个新的会话ID或删除当前的会话ID,并将其发送给响应请求。

我认为这可以让我在适当的时候使用常规REST API和基本身份验证,并维护会话/记住我的功能。它不解决多个登录问题,但否则我认为这样应该会。请告诉我。

我将使用基于令牌的身份验证,您可以在每个请求中自动发送令牌(自动)。您必须登录一次,服务器将为您提供一个令牌,然后您可以使用每个请求发送。该标记将被添加到HTML标题中,以便您不必将每个请求修改为浏览器。

您可以在API中设置某些呼叫,以便它们始终需要令牌,而其他呼叫可能不受令牌保护。

对于Express,可以使用express-jwt(https://www.npmjs.org/package/express-jwt)

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

// Protect the /api routes with JWT
app.use('/api',expressJwt({secret: secret}));

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

如果要进行身份验证,您可以在快速服务器中创建此功能:

app.post('/authenticate',function (req,res) {
  //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开头的东西:

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

在您的Angular应用程序中,您可以登录:

$http
      .post('/authenticate',$scope.user)
      .success(function (data,status,headers,config) {
        $window.sessionStorage.token = data.token;
        $scope.message = 'Welcome';
      })
      .error(function (data,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';
      });

并通过创建一个身份验证拦截器,它将自动发送令牌与每个请求:

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');
});

如果您必须支持不支持本地存储的旧浏览器。您可以使用像AmplifyJS(http://amplifyjs.com/)这样的库来交换$ window.sessionStorage。扩大例如使用任何本地存储可用。这将会像这样翻译:

if (data.status === 'OK') {
      //Save the data using Amplify.js
      localStorage.save('sessionToken',data.token);
      //This doesn't work on the file protocol or on some older browsers
      //$window.sessionStorage.token = data.token;
      $location.path('/pep');
    }
  }).error(function (error) {
    // Erase the token if the user fails to log in
    localStorage.save('sessionToken',null);
    // Handle login errors here
    $scope.message = 'Error: Invalid user or password';
  });

和我们交换的authinterpter:

angular.module('myApp.authInterceptor',['myApp.localStorage']).factory('authInterceptor',[
  '$rootScope','$q','localStorage',localStorage) {
    return {
      request: function (config) {
        config.headers = config.headers || {};
        config.headers.Authorization = 'Bearer ' + localStorage.retrieve('sessionToken');
        return config;
      },response: function (response) {
        if (response.status === 401) {
        }
        return response || $q.when(response);
      }
    };
  }
]);

您可以在本文中找到除AmplifyJS之外的所有内容:

http://blog.auth0.com/2014/01/07/angularjs-authentication-with-cookies-vs-token/

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读