在Satellizer中将Facebook登录集成到AngularJS App中

本文概述

  • 身份验证与授权
  • 为什么要使用Satellizer
  • 使用Facebook登录的AngularJS应用
  • 总结
随着功能丰富的前端框架(例如AngularJS)的出现, 越来越多的逻辑正在前端实现, 例如数据操作/验证, 身份验证等。 Satellizer是AngularJS易于使用的基于令牌的身份验证模块, 它简化了在AngularJS中实施身份验证机制的过程。该库内置了对Google, Facebook, LinkedIn, Twitter, Instagram, GitHub, Bitbucket, Yahoo, Twitch的支持和Microsoft(Windows Live)帐户。
在本文中, 我们将构建一个非常简单的webapp, 类似于此处的webapp, 你可以登录并查看当前用户的信息。
身份验证与授权 一旦你的应用开始集成用户系统, 你通常会遇到2个可怕的词。根据维基百科:
认证是确认实体声称为真的单条数据(数据)属性的真实性的行为。
授权是指定通常对与信息安全和计算机安全有关的资源的访问权限, 特别是对访问控制的访问权限的功能。
用通俗易懂的术语, 让我们以一个博客网站为例, 其中有人在工作。博主撰写文章, 经理验证内容。每个人都可以向系统进行身份验证(登录), 但是他们的权限(授权)不同, 因此博客作者无法验证内容, 而经理可以。
为什么要使用Satellizer 你可以通过遵循一些教程(例如非常详细的教程)在AngularJS中创建自己的身份验证系统:JSON Web令牌教程:Laravel和AngularJS中的示例。我建议阅读这篇文章, 因为它很好地解释了JWT(JSON Web令牌), 并展示了一种直接使用本地存储和HTTP拦截器在AngularJS中实现身份验证的简单方法。
那为什么要使用Satellizer化器呢?主要原因是它支持少数社交网络登录, 例如Facebook, Twitter等。如今, 尤其是对于在移动设备上使用的网站, 键入用户名和密码非常麻烦, 并且用户希望能够无障碍地使用你的网站。通过使用社交登录。由于集成每个社交网络的SDK并遵循其文档非常重复, 因此以最少的努力支持这些社交登录将是很好的。
此外, Satellizer是Github上的一个活跃项目。主动是此处的关键, 因为这些SDK经常更改, 并且你不希望时不时地阅读其文档(使用Facebook SDK的人都知道这很烦人)
使用Facebook登录的AngularJS应用 这是事情开始变得有趣的地方。
我们将构建一个具有常规登录/注册(即使用用户名, 密码)机制并支持社交登录的网络应用。这个webapp非常简单, 因为它只有3个页面:
  • 主页:任何人都可以看到
  • 登录页面:输入用户名/密码
  • 秘密页面:只有登录用户才能看到
对于后端, 我们将使用Python和Flask。 Python和Flask框架具有很好的表达能力, 因此我希望将代码移植到其他语言/框架不会很困难。当然, 我们将使用AngularJS作为前端。对于社交登录, 我们将仅与Facebook集成, 因为它是当前最受欢迎的社交网络。
开始吧!
步骤1:Bootstrap项目
这是我们构造代码的方式:
- app.py - static/ - index.html - app.js - bower.json - partials/ - login.tpl.html - home.tpl.html - secret.tpl.html

所有的后端代码都在app.py中。前端代码放在static /文件夹中。默认情况下, Flask将自动提供static /文件夹的内容。所有的部分视图都在static / partials /中, 并由ui.router模块处理。
要开始对后端进行编码, 我们需要Python 2.7。*并使用pip安装所需的库。你当然可以使用virtualenv隔离Python环境。以下是放置在requirements.txt中所需的Python模块列表:
Flask==0.10.1 PyJWT==1.4.0 Flask-SQLAlchemy==1.0 requests==2.7.0

要安装所有这些依赖项:
pip install -r requirements.txt

在app.py中, 我们有一些初始代码来引导Flask(为简洁起见, 省略了import语句):
app = Flask(__name__)@app.route('/') def index(): return flask.redirect('/static/index.html')if __name__ == '__main__': app.run(debug=True)

接下来, 我们启动bower并安装AngularJS和ui.router:
bower init # here you will need to answer some question. when in doubt, just hit enter :) bower install angular angular-ui-router --save # install and save these dependencies into bower.json

安装这些库之后, 我们需要在index.html中包含AngularJS和ui-router并为3个页面创建路由:主页, 登录名和密钥。
< body ng-app="DemoApp"> < a ui-sref="home"> Home< /a> < a ui-sref="login"> Login< /a> < a ui-sref="secret"> Secret< /a> < div ui-view> < /div> < script src="http://www.srcmini.com/bower_components/angular/angular.min.js"> < /script> < script src="http://www.srcmini.com/bower_components/angular-ui-router/release/angular-ui-router.min.js"> < /script> < script src="http://www.srcmini.com/main.js"> < /script> < /body>

下面是在main.js中配置路由所需的代码:
var app = angular.module('DemoApp', ['ui.router']); app.config(function ($stateProvider, $urlRouterProvider) { $stateProvider .state('home', { url: '/home', templateUrl: 'partials/home.tpl.html' }) .state('secret', { url: '/secret', templateUrl: 'partials/secret.tpl.html', }) .state('login', { url: '/login', templateUrl: 'partials/login.tpl.html' }); $urlRouterProvider.otherwise('/home'); });

此时, 如果你运行服务器python app.py, 则应该在http:// localhost:5000上具有此基本接口
在Satellizer中将Facebook登录集成到AngularJS App中

文章图片
此时, “ 主页” , “ 登录” 和” 秘密” 链接应该可以正常工作, 并显示相应模板的内容。
恭喜, 你刚刚完成了骨架的设置!如果遇到任何错误, 请在GitHub上检查代码
步骤2:登录和注册
完成此步骤后, 你将拥有一个网络应用程序, 可以使用电子邮件和密码进行注册/登录。
第一步是配置后端。我们需要一个用户模型和一种为给定用户生成JWT令牌的方法。下面显示的用户模型确实得到了简化, 甚至不执行任何基本检查, 例如现场电子邮件是否包含” @” , 或者现场密码是否包含至少6个字符, 等等。
class User(db.Model): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(100), nullable=False) password = db.Column(db.String(100))def token(self): payload = { 'sub': self.id, 'iat': datetime.utcnow(), 'exp': datetime.utcnow() + timedelta(days=14) } token = jwt.encode(payload, app.config['TOKEN_SECRET']) return token.decode('unicode_escape')

我们在python中使用jwt模块在JWT中生成有效负载部分。 iat和exp部分对应于令牌创建和过期的时间戳。在此代码中, 令牌将在2周后过期。
创建用户模型之后, 我们可以添加” 登录” 和” 注册” 端点。两者的代码非常相似, 因此在这里我将仅展示” 注册” 部分。请注意, 默认情况下, Satellizer将分别为” 登录” 和” 注册” 调用端点/ auth / login和/ auth / signup。
@app.route('/auth/signup', methods=['POST']) def signup(): data = http://www.srcmini.com/request.jsonemail = data["email"] password = data["password"]user = User(email=email, password=password) db.session.add(user) db.session.commit()return jsonify(token=user.token())

让我们先使用curl检查端点:
curl localhost:5000/auth/signup -H "Content-Type: application/json" -X POST -d '{"email":"[email  protected]", "password":"xyz"}'

结果应如下所示:
{ "token": "very long string…." }

现在已经准备好后端部分, 让我们来攻击前端!首先, 我们需要安装satellizer并将其添加为main.js中的依赖项:
bower install satellizer --save

添加Satellizer化器作为依赖项:
var app = angular.module('DemoApp', ['ui.router', 'satellizer']);

与到目前为止的所有设置相比, satellizer中的登录和注册实际上非常简单:
$scope.signUp = function () { $auth .signup({email: $scope.email, password: $scope.password}) .then(function (response) { // set the token received from server $auth.setToken(response); // go to secret page $state.go('secret'); }) .catch(function (response) { console.log("error response", response); }) };

如果你在设置代码时遇到任何困难, 可以在GitHub上查看代码。
步骤#3:但是秘密视图并不是真正的秘密, 因为任何人都可以看到它!
对, 那是正确的!到现在为止, 任何人都可以不登录而进入秘密页面。
现在是时候在AngularJS中添加一些拦截器了, 以确保如果有人进入了秘密页面并且该用户未登录, 他们将被重定向到登录页面。
首先, 我们应该添加一个标记requiredLogin来区分秘密页面和其他页面。
.state('secret', { url: '/secret', templateUrl: 'partials/secret.tpl.html', controller: 'SecretCtrl', data: {requiredLogin: true} })

$ dataChangeStart事件中将使用” 数据” 部分, 每次路由更改时都会触发该事件:
app.run(function ($rootScope, $state, $auth) { $rootScope.$on('$stateChangeStart', function (event, toState) { var requiredLogin = false; // check if this state need login if (toState.data & & toState.data.requiredLogin) requiredLogin = true; // if yes and if this user is not logged in, redirect him to login page if (requiredLogin & & !$auth.isAuthenticated()) { event.preventDefault(); $state.go('login'); } }); });

现在, 用户必须先登录才能直接进入机密页面。
与往常一样, 此步骤的代码可以在此处找到。
步骤#4:是时候获得一些真正的秘密了!
目前, 秘密页面中没有任何真正的秘密。让我们在这里放一些私人的东西。
此步骤开始于在后端中创建一个端点, 该端点只能由经过身份验证的用户访问, 例如具有有效令牌。下面的端点/ user返回与令牌对应的用户的user_id和电子邮件。
@app.route('/user') def user_info(): # the token is put in the Authorization header if not request.headers.get('Authorization'): return jsonify(error='Authorization header missing'), 401# this header looks like this: "Authorization: Bearer {token}" token = request.headers.get('Authorization').split()[1] try: payload = jwt.decode(token, app.config['TOKEN_SECRET']) except DecodeError: return jsonify(error='Invalid token'), 401 except ExpiredSignature: return jsonify(error='Expired token'), 401 else: user_id = payload['sub'] user = User.query.filter_by(id=user_id).first() if user is None: return jsonify(error='Should not happen ...'), 500 return jsonify(id=user.id, email=user.email), 200 return jsonify(error="never reach here..."), 500

同样, 我们利用模块jwt解码” 授权” 标头中包含的JWT令牌, 并处理令牌过期或无效的情况。
让我们使用curl测试此端点。首先, 我们需要获得一个有效的令牌:
curl localhost:5000/auth/signup -H "Content-Type: application/json" -X POST -d '{"email":"[email  protected]", "password":"xyz"}'

然后使用此令牌:
curl localhost:5000/user -H "Authorization: Bearer {put the token here}"

得到以下结果:
{ "email": "[email  protected]", "id": 1 }

现在, 我们需要将此端点包括在Secret Controller中。这非常简单, 因为我们只需要使用常规的$ http模块调用端点即可。令牌由Satellizer自动插入到标头中, 因此我们无需理会保存令牌并将其放入正确标头中的所有细节。
getUserInfo(); function getUserInfo() { $http.get('/user') .then(function (response) { $scope.user = response.data; }) .catch(function (response) { console.log("getUserInfo error", response); }) }

最后, 我们在秘密页面中拥有真正私人的东西!
在Satellizer中将Facebook登录集成到AngularJS App中

文章图片
此步骤的代码在GitHub上。
步骤5:使用Satellizer进行Facebook登录
正如开头提到的, 有关Satellizer的一件好事是, 它使集成社交登录更加容易。在此步骤结束时, 用户可以使用其Facebook帐户登录!
在Satellizer中将Facebook登录集成到AngularJS App中

文章图片
首先要做的是在Facebook开发人员页面上创建一个应用程序, 以获取application_id和密码。如果你还没有Facebook开发者帐户, 请按照developers.facebook.com/docs/apps/register创建一个Facebook开发者帐户, 然后创建一个网站应用。之后, 你将具有应用程序ID和应用程序密码, 如下面的屏幕快照所示。
在Satellizer中将Facebook登录集成到AngularJS App中

文章图片
一旦用户选择与Facebook连接, Satellizer就会将授权代码发送到端点/ auth / facebook。使用此授权代码, 后端可以从Facebook / oauth端点检索访问令牌, 该访问令牌允许对Facebook Graph API的调用来获取用户信息, 例如位置, user_friends, 用户电子邮件等。
我们还需要跟踪用户帐户是使用Facebook还是通过常规注册创建的。为此, 我们将facebook_id添加到我们的用户模型。
facebook_id = db.Column(db.String(100))

通过我们添加到app.config的环境变量FACEBOOK_SECRET来配置facebook机密。
app.config['FACEBOOK_SECRET'] = os.environ.get('FACEBOOK_SECRET')

因此, 要启动app.py, 你应该设置以下env变量:
FACEBOOK_SECRET={your secret} python app.py

这是处理Facebook登录的方法。默认情况下, Satellizer将调用端点/ auth / facebook。
@app.route('/auth/facebook', methods=['POST']) def auth_facebook(): access_token_url = 'https://graph.facebook.com/v2.3/oauth/access_token' graph_api_url = 'https://graph.facebook.com/v2.5/me?fields=id, email'params = { 'client_id': request.json['clientId'], 'redirect_uri': request.json['redirectUri'], 'client_secret': app.config['FACEBOOK_SECRET'], 'code': request.json['code'] }# Exchange authorization code for access token. r = requests.get(access_token_url, params=params) # use json.loads instead of urlparse.parse_qsl access_token = json.loads(r.text)# Step 2. Retrieve information about the current user. r = requests.get(graph_api_url, params=access_token) profile = json.loads(r.text)# Step 3. Create a new account or return an existing one. user = User.query.filter_by(facebook_id=profile['id']).first() if user: return jsonify(token=user.token())u = User(facebook_id=profile['id'], email=profile['email']) db.session.add(u) db.session.commit() return jsonify(token=u.token())

要将请求发送到Facebook服务器, 我们使用方便的模块请求。现在, 后端的困难部分已经完成。在前端, 添加Facebook登录非常简单。首先, 我们需要通过将以下代码添加到app.config函数中来告诉Satellizer我们的facebook_id:
$authProvider.facebook({ clientId: {your facebook app id}, // by default, the redirect URI is http://localhost:5000 redirectUri: 'http://localhost:5000/static/index.html' });

要使用Facebook登录, 我们可以致电:
$auth.authenticate("facebook")

和往常一样, 你可以在GitHub上检查代码
目前, 该Web应用程序在功能方面已经完成。用户可以使用常规电子邮件和密码或使用Facebook登录/注册。登录后, 用户可以看到其秘密页面。
制作漂亮的界面
此时界面还不是很漂亮, 所以让我们为布局和Angle Toaster模块添加一些Bootstrap, 以很好地处理错误消息, 例如登录失败时。
美化部分的代码可以在这里找到。
总结 本文显示了Satellizer在(简单的)AngularJS Webapp中的逐步集成。借助Satellizer, 我们可以轻松添加其他社交登录信息, 例如Twitter, Linkedin等。前端的代码与本文中的代码完全相同。但是, 后端会有所不同, 因为社交网络SDK的终结点具有不同的协议。你可以查看https://github.com/sahat/satellizer/blob/master/examples/server/python/app.py, 其中包含Facebook, Github, Google, Linkedin, Twiter和Bitbucket的示例。如有疑问, 应查看https://github.com/sahat/satellizer上的文档。
【在Satellizer中将Facebook登录集成到AngularJS App中】相关:使用区块链的一键式登录:MetaMask教程

    推荐阅读