composer-rest-server认证实现
在composer里面关于用户有两种模式。
- 多用户模式,用户为参与者。和composer-rest-server并无太大关系,仅作为智能合约里面的参与者。用户通过认证,可以独立执行composer-rest-server,以实现权限隔离。
- 认证模式。多个用户(不是参与者)访问同一个restful接口,需要做一定的认证操作,避免对区块链的过度访问。这种模式实在compsoser-rest-server层面发生的,认证过程不会和区块链有任何互动。
这篇文章所讲的就是第二种方式。
composer-rest-server是通过loopback构建的一个项目,所以权限管理大致和loopback相同。
这里提供两种方式供选择
-
直接使用loopback用户认证(推荐)
loopback提供了简单的用户模块,在composer的实现中,用户被隐藏起来了,所以只需要开放登录、登出接口即可。需要解决的问题:
- composer实现只是在内存保存了数据。如果需要管理用户,需要使用数据库
- 开放user数据模块之后,开放的接口太多,需要隐藏一部分
解决方式
- 修改 /server/datasources.json 为
{ "db": { "name": "db", "connector": "memory" }, //添加mysql依赖。注意:使用mysql需要在package.json添加 "loopback-connector-mysql":"5.2.0" 依赖 "mysqlDs": { "name": "mysqlDs", "connector": "mysql", "host": "localhost", "port": 3306, "database": "db_rest_server", //需新建数据库和user表。 "username": "root", "password": "123456" } }
- 修改 /server/model-config.json
... "user": { "dataSource": "mysqlDs", //修改数据源 memory 为 mysql "public": true //开发 }, ...
- 新增脚本 /server/root/create-models.js
loopback里面,server/boot 下面的脚本会在程序启动的时候执行
'use strict'; module.exports = function(app) { //FIXME only run this script AT first TIME . For create table. // app.dataSources.mysqlDs.automigrate('user', function(err) { // if (err) throw err; // // app.models.user.create([{ // username: 'test1', // email:'test1@email.com', // password: 'test1', // }], function(err, coffeeShops) { // if (err) throw err; // console.log('Models created: \n', coffeeShops); // }); // }); app.models.user.disableRemoteMethodByName("upsert"); // disables PATCH /app.models.users app.models.user.disableRemoteMethodByName("find"); // disables GET /app.models.users app.models.user.disableRemoteMethodByName("replaceOrCreate"); // disables PUT /app.models.users app.models.user.disableRemoteMethodByName("create"); // disables POST /app.models.users app.models.user.disableRemoteMethodByName("prototype.updateAttributes"); // disables PATCH /app.models.users/{id} app.models.user.disableRemoteMethodByName("findById"); // disables GET /app.models.users/{id} app.models.user.disableRemoteMethodByName("exists"); // disables HEAD /app.models.users/{id} app.models.user.disableRemoteMethodByName("replaceById"); // disables PUT /app.models.users/{id} app.models.user.disableRemoteMethodByName("deleteById"); // disables DELETE /app.models.users/{id} app.models.user.disableRemoteMethodByName('prototype.__get__accessTokens'); // disable GET /app.models.users/{id}/accessTokens app.models.user.disableRemoteMethodByName('prototype.__create__accessTokens'); // disable POST /app.models.users/{id}/accessTokens app.models.user.disableRemoteMethodByName('prototype.__delete__accessTokens'); // disable DELETE /app.models.users/{id}/accessTokens app.models.user.disableRemoteMethodByName('prototype.__get__credentials'); // disable GET /app.models.users/{id}/accessTokens app.models.user.disableRemoteMethodByName('prototype.__create__credentials'); // disable POST /app.models.users/{id}/accessTokens app.models.user.disableRemoteMethodByName('prototype.__delete__credentials'); // disable DELETE /app.models.users/{id}/accessTokens app.models.user.disableRemoteMethodByName('prototype.__get__identities'); // disable GET /app.models.users/{id}/accessTokens app.models.user.disableRemoteMethodByName('prototype.__create__identities'); // disable POST /app.models.users/{id}/accessTokens app.models.user.disableRemoteMethodByName('prototype.__delete__identities'); // disable DELETE /app.models.users/{id}/accessTokens app.models.user.disableRemoteMethodByName('prototype.__findById__accessTokens'); // disable GET /app.models.users/{id}/accessTokens/{fk} app.models.user.disableRemoteMethodByName('prototype.__updateById__accessTokens'); // disable PUT /app.models.users/{id}/accessTokens/{fk} app.models.user.disableRemoteMethodByName('prototype.__destroyById__accessTokens');// disable DELETE /app.models.users/{id}/accessTokens/{fk} app.models.user.disableRemoteMethodByName('prototype.__findById__identities'); // disable GET /app.models.users/{id}/accessTokens/{fk} app.models.user.disableRemoteMethodByName('prototype.__updateById__identities'); // disable PUT /app.models.users/{id}/accessTokens/{fk} app.models.user.disableRemoteMethodByName('prototype.__destroyById__identities');// disable DELETE /app.models.users/{id}/accessTokens/{fk} app.models.user.disableRemoteMethodByName('prototype.__findById__credentials'); // disable GET /app.models.users/{id}/accessTokens/{fk} app.models.user.disableRemoteMethodByName('prototype.__updateById__credentials'); // disable PUT /app.models.users/{id}/accessTokens/{fk} app.models.user.disableRemoteMethodByName('prototype.__destroyById__credentials');// disable DELETE /app.models.users/{id}/accessTokens/{fk} app.models.user.disableRemoteMethodByName('prototype.__count__accessTokens'); // disable GET /app.models.users/{id}/accessTokens/count app.models.user.disableRemoteMethodByName('prototype.__count__credentials'); // disable GET /app.models.users/{id}/accessTokens/count app.models.user.disableRemoteMethodByName('prototype.__count__identities'); // disable GET /app.models.users/{id}/accessTokens/count app.models.user.disableRemoteMethodByName("prototype.verify"); // disable POST /app.models.users/{id}/verify app.models.user.disableRemoteMethodByName("changePassword"); // disable POST /app.models.users/change-password app.models.user.disableRemoteMethodByName("createChangeStream"); // disable GET and POST /app.models.users/change-stream app.models.user.disableRemoteMethodByName("confirm"); // disables GET /app.models.users/confirm app.models.user.disableRemoteMethodByName("count"); // disables GET /app.models.users/count app.models.user.disableRemoteMethodByName("findOne"); // disables GET /app.models.users/findOne //app.models.user.disableRemoteMethodByName("login"); // disables POST /app.models.users/login //app.models.user.disableRemoteMethodByName("logout"); // disables POST /app.models.users/logout app.models.user.disableRemoteMethodByName("resetPassword"); // disables POST /app.models.users/reset app.models.user.disableRemoteMethodByName("setPassword"); // disables POST /app.models.users/reset-password app.models.user.disableRemoteMethodByName("update"); // disables POST /app.models.users/update app.models.user.disableRemoteMethodByName("upsertWithWhere"); // disables POST /app.models.users/upsertWithWhere };
- composer-rest-server-local -c cardName -a true [-n never] 启动服务
在user表新建一条数据。使用 /user/login ,即可获取accessToken。在之后的请求里面,添加请求头:X-Access-Token: 对应token ,即可获取认证通过。
-
passport实现认证
passport是一个用来专门管理用户登录的一个库。包含n多第三方登录,已经local登录。适用于任何express扩展出来的项目。
但是这个的针对auth、auth2等做的个库,所以如果是想提供直接提供api以获得token有些麻烦。
使用方式:
修改 /server/providers.json
{ "local": { //名称 "provider": "local", "module": "passport-local", //这里表示使用本地用户。还有:github、google等授权库 "usernameField": "username", //必须字段 "passwordField": "password", "authPath": "/auth/local", //认证跳转地址 "successRedirect": "/", //成功回调 "failureRedirect": "/" //失败回调 } }
直接访问设置的认证地址,在回调地址里面的session就能获取到accessToken。
遇到的问题:
本来是计划直接接入passport-local,不暴露user模块的,但是发现获取token方式太复杂,涉及到重定向,针对调用不友好,所以放弃了。为了避免修改loopback-componet-passport包内容,所以建议直接使用方式1.
网友评论