Commit 2201e360ff31d4c08f1449cb3dafcdaf0d270a90
1 parent
bc6e4c53
Le login se fait désormais de manière encryptée
Showing
15 changed files
with
241 additions
and
154 deletions
Show diff stats
@@ -0,0 +1,36 @@ | @@ -0,0 +1,36 @@ | ||
1 | +var ursa = require('ursa'); | ||
2 | +var fs = require('fs'); | ||
3 | + | ||
4 | +var decrypt = {}; | ||
5 | + | ||
6 | +decrypt.decrypter = false; | ||
7 | + | ||
8 | +decrypt.whenOk = function (cb) { | ||
9 | + if (this.encrypter) { | ||
10 | + cb(); | ||
11 | + } else { | ||
12 | + this.prepare(cb); | ||
13 | + } | ||
14 | +}; | ||
15 | + | ||
16 | +decrypt.prepare = function (cb) { | ||
17 | + fs.readFile('config/ci_com.pem', function(err, data) { | ||
18 | + if (err) { | ||
19 | + throw err; | ||
20 | + } | ||
21 | + this.decrypter = ursa.createPrivateKey(data); | ||
22 | + cb(); | ||
23 | + }); | ||
24 | +}; | ||
25 | + | ||
26 | +decrypt.preload = function(cb) { | ||
27 | + this.whenOk(cb); | ||
28 | +}; | ||
29 | + | ||
30 | +decrypt.decrypt = function (string, cb) { | ||
31 | + this.whenOk(function() { | ||
32 | + cb(this.decrypter.decrypt(string, 'base64', 'utf8', ursa.RSA_PKCS1_PADDING)); | ||
33 | + }); | ||
34 | +}; | ||
35 | + | ||
36 | +module.exports = decrypt; |
app/controllers/sessions.js
app/routes/api.js
1 | var membres = require('../controllers/membres'); | 1 | var membres = require('../controllers/membres'); |
2 | var sessions = require('../controllers/sessions'); | 2 | var sessions = require('../controllers/sessions'); |
3 | +var decrypt = require('../controllers/decrypt'); | ||
3 | var express = require('express'); | 4 | var express = require('express'); |
4 | 5 | ||
5 | -var api = express() | 6 | +var api = express(); |
6 | 7 | ||
7 | // Sessions | 8 | // Sessions |
8 | api.get('/session', function (req, res) { // Informations sur la session | 9 | api.get('/session', function (req, res) { // Informations sur la session |
9 | - if (req.cookies && req.cookies.session) { | ||
10 | - sessions.use(req.cookies.session, function (err) { | ||
11 | - if (err) { | ||
12 | - res.send(err) | ||
13 | - } else { | ||
14 | - res.send(sessions.cur) | ||
15 | - } | ||
16 | - }) | ||
17 | - // TODO si pas bon : res.clearCookie('session') | ||
18 | - } else { | ||
19 | - res.send('missing'); | ||
20 | - } | 10 | + if (req.cookies && req.cookies.session) { |
11 | + sessions.use(req.cookies.session, function (err) { | ||
12 | + if (err) { | ||
13 | + res.send(err); | ||
14 | + } else { | ||
15 | + res.send(sessions.cur); | ||
16 | + } | ||
17 | + }); | ||
18 | + // TODO si pas bon : res.clearCookie('session') | ||
19 | + } else { | ||
20 | + res.send('missing'); | ||
21 | + } | ||
21 | }); | 22 | }); |
22 | 23 | ||
23 | api.post('/session', function (req, res) { // Se connecter | 24 | api.post('/session', function (req, res) { // Se connecter |
24 | - sessions.open(req.body, function (err) { | ||
25 | - if (err) { | ||
26 | - res.send(err) | ||
27 | - } else { | ||
28 | - res.cookie('session', sessions.cur._id); | ||
29 | - res.send(sessions.cur) | ||
30 | - } | ||
31 | - }) | ||
32 | -}) | 25 | + decrypt.decrypt(req.body[0], function (data) { |
26 | + sessions.open(JSON.parse(data), function (err) { | ||
27 | + if (err) { | ||
28 | + res.send(err); | ||
29 | + } else { | ||
30 | + res.cookie('session', sessions.cur._id); | ||
31 | + res.send(sessions.cur); | ||
32 | + } | ||
33 | + }); | ||
34 | + }); | ||
35 | +}); | ||
33 | 36 | ||
34 | api.delete('/session', function (req, res) { // Se déconnecter | 37 | api.delete('/session', function (req, res) { // Se déconnecter |
35 | - if (req.cookies.session) { | ||
36 | - sessions.delete(req.cookies.session, function () { | ||
37 | - res.clearCookie('session'); | ||
38 | - res.end() | ||
39 | - }) | ||
40 | - } else { | ||
41 | - res.send('missing') | ||
42 | - } | ||
43 | -}) | 38 | + if (req.cookies.session) { |
39 | + sessions.delete(req.cookies.session, function () { | ||
40 | + res.clearCookie('session'); | ||
41 | + res.end(); | ||
42 | + }); | ||
43 | + } else { | ||
44 | + res.send('missing'); | ||
45 | + } | ||
46 | +}); | ||
44 | 47 | ||
45 | ifPermission = function (req, res, perm, cb) { | 48 | ifPermission = function (req, res, perm, cb) { |
46 | - sessions.use(req.cookies.session, function (err) { | ||
47 | - if (err) { | ||
48 | - res.status(403).end() | ||
49 | - } else { | ||
50 | - if (sessions.cur[perm]) { | ||
51 | - cb() | ||
52 | - } else { | ||
53 | - res.status(403).end() | ||
54 | - } | ||
55 | - } | ||
56 | - }) | ||
57 | -} | 49 | + sessions.use(req.cookies.session, function (err) { |
50 | + if (err) { | ||
51 | + res.status(403).end(); | ||
52 | + } else { | ||
53 | + if (sessions.cur[perm]) { | ||
54 | + cb(); | ||
55 | + } else { | ||
56 | + res.status(403).end(); | ||
57 | + } | ||
58 | + } | ||
59 | + }); | ||
60 | +}; | ||
58 | 61 | ||
59 | 62 | ||
60 | // Membres | 63 | // Membres |
61 | api.get('/membres', function (req, res) { // Liste des membres | 64 | api.get('/membres', function (req, res) { // Liste des membres |
62 | - membres.list(function (err, membres) { | ||
63 | - if (err) | ||
64 | - res.send(err); | ||
65 | - res.json(membres); | ||
66 | - }); | 65 | + membres.list(function (err, membres) { |
66 | + if (err) | ||
67 | + res.send(err); | ||
68 | + res.json(membres); | ||
69 | + }); | ||
67 | }); | 70 | }); |
68 | 71 | ||
69 | api.post('/membres', function (req, res) { // Ajout d'un membre | 72 | api.post('/membres', function (req, res) { // Ajout d'un membre |
70 | - ifPermission(req, res, 'canAddMembre', function () { | ||
71 | - membres.add(req.body, function (err, membre) { | ||
72 | - if (err) | ||
73 | - res.send(err); | ||
74 | - membres.list(function (err, membres) { | ||
75 | - if (err) | ||
76 | - res.send(err); | ||
77 | - res.json(membres); | ||
78 | - }); | ||
79 | - }); | ||
80 | - }) | 73 | + ifPermission(req, res, 'canAddMembre', function () { |
74 | + membres.add(req.body, function (err, membre) { | ||
75 | + if (err) | ||
76 | + res.send(err); | ||
77 | + membres.list(function (err, membres) { | ||
78 | + if (err) | ||
79 | + res.send(err); | ||
80 | + res.json(membres); | ||
81 | + }); | ||
82 | + }); | ||
83 | + }); | ||
81 | }); | 84 | }); |
82 | 85 | ||
83 | api.delete('/membres/:membre_id', function (req, res) { // Supression d'un membre | 86 | api.delete('/membres/:membre_id', function (req, res) { // Supression d'un membre |
84 | - ifPermission(req, res, 'canDelMembre', function () { | ||
85 | - membres.remove(req.params.membre_id, function (err, membre) { | ||
86 | - if (err) | ||
87 | - res.send(err); | ||
88 | - membres.list(function (err, membres) { | ||
89 | - if (err) | ||
90 | - res.send(err); | ||
91 | - res.json(membres); | ||
92 | - }); | ||
93 | - }); | ||
94 | - }) | ||
95 | -}) | 87 | + ifPermission(req, res, 'canDelMembre', function () { |
88 | + membres.remove(req.params.membre_id, function (err, membre) { | ||
89 | + if (err) | ||
90 | + res.send(err); | ||
91 | + membres.list(function (err, membres) { | ||
92 | + if (err) | ||
93 | + res.send(err); | ||
94 | + res.json(membres); | ||
95 | + }); | ||
96 | + }); | ||
97 | + }); | ||
98 | +}); | ||
96 | 99 | ||
97 | -module.exports = api; | ||
98 | \ No newline at end of file | 100 | \ No newline at end of file |
101 | +module.exports = api; |
bower.json
@@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
5 | "font-awesome": "latest", | 5 | "font-awesome": "latest", |
6 | "angular": "latest", | 6 | "angular": "latest", |
7 | "angular-route": "latest", | 7 | "angular-route": "latest", |
8 | - "bootswatch-dist": "3.3.2-cerulean" | 8 | + "bootswatch-dist": "3.3.2-cerulean", |
9 | + "jsencrypt": "~2.1.0" | ||
9 | } | 10 | } |
10 | } | 11 | } |
package.json
@@ -9,6 +9,7 @@ | @@ -9,6 +9,7 @@ | ||
9 | "method-override": "^2.3.1", | 9 | "method-override": "^2.3.1", |
10 | "mongoose": "^3.8.25", | 10 | "mongoose": "^3.8.25", |
11 | "morgan": "^1.5.1", | 11 | "morgan": "^1.5.1", |
12 | - "node-line-reader": "0.0.2" | 12 | + "node-line-reader": "0.0.2", |
13 | + "ursa": "^0.8.4" | ||
13 | } | 14 | } |
14 | } | 15 | } |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +Même pas en rêve ! |
public/js/app.js
1 | -angular.module('ciApp', ['ngRoute', 'appRoutes', 'SessionsServ', 'SessionsCtrl', 'ConnectCtrl', 'MembreCtrl']); | ||
2 | \ No newline at end of file | 1 | \ No newline at end of file |
2 | +angular.module('ciApp', ['ngRoute', 'appRoutes', 'EncryptServ', 'SessionsServ', 'SessionsCtrl', 'ConnectCtrl', 'MembreCtrl']); |
public/js/controllers/ConnectCtrl.js
1 | -angular.module('ConnectCtrl', []).controller('ConnectController', ['$scope', 'SessionService', | ||
2 | - function ($scope, SessionService) { | ||
3 | - $scope.connect = { | ||
4 | - connect: function () { | ||
5 | - SessionService.connect($scope.connect.login, $scope.connect.pass) | ||
6 | - } | ||
7 | - } | ||
8 | - } | ||
9 | -]); | ||
10 | \ No newline at end of file | 1 | \ No newline at end of file |
2 | +angular.module('ConnectCtrl', []).controller('ConnectController', ['$scope', 'SessionService', 'EncryptService', | ||
3 | + function ($scope, SessionService, EncryptService) { | ||
4 | + EncryptService.preload(function () { | ||
5 | + return undefined; | ||
6 | + }); | ||
7 | + $scope.connect = { | ||
8 | + connect: function () { | ||
9 | + SessionService.connect($scope.connect.login, $scope.connect.pass); | ||
10 | + } | ||
11 | + }; | ||
12 | + } | ||
13 | +]); |
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +angular.module('EncryptServ', []).service('EncryptService', ['$http', | ||
2 | + function ($http) { | ||
3 | + a = { | ||
4 | + encrypter: false, | ||
5 | + whenOk: function (cb) { | ||
6 | + if (this.encrypter) { | ||
7 | + cb(); | ||
8 | + } else { | ||
9 | + this.prepare(cb); | ||
10 | + } | ||
11 | + }, | ||
12 | + prepare: function (cb) { | ||
13 | + $http.get('/com/ci_com_pub.pem').success(function (key) { | ||
14 | + this.encrypter = new JSEncrypt(); | ||
15 | + this.encrypter.setPublicKey(key); | ||
16 | + cb(); | ||
17 | + }); | ||
18 | + }, | ||
19 | + preload: function(cb) { | ||
20 | + this.whenOk(cb); | ||
21 | + }, | ||
22 | + encrypt: function (string, cb) { | ||
23 | + this.whenOk(function() { | ||
24 | + cb(this.encrypter.encrypt(string)); | ||
25 | + }); | ||
26 | + } | ||
27 | + }; | ||
28 | + return a; | ||
29 | + } | ||
30 | +]); |
public/js/services/SessionServ.js
1 | -angular.module('SessionsServ', []).service('SessionService', ['$http', | ||
2 | - function ($http) { | ||
3 | - a = { | ||
4 | - cur: false, | ||
5 | - status: 0, | ||
6 | - changeHandlers: [], | ||
7 | - onChange: function (fun) { | ||
8 | - this.changeHandlers.push(fun) | ||
9 | - }, | ||
10 | - triggerChange: function () { | ||
11 | - for (fun in this.changeHandlers) { | ||
12 | - this.changeHandlers[fun]() | ||
13 | - } | ||
14 | - }, | ||
15 | - updateSessionInfos: function (data) { | ||
16 | - console.log("Connection:", data) | ||
17 | - if (typeof data === 'object') { | ||
18 | - this.cur = data | ||
19 | - } else { | ||
20 | - this.cur = false | ||
21 | - } | ||
22 | - this.triggerChange() | ||
23 | - }, | ||
24 | - get: function (cb) { // Fetch infos if needed | ||
25 | - if (status == 0) { | ||
26 | - this.status = 1 // Fetching | ||
27 | - _this = this | ||
28 | - // TODO Verify if cookies to prevent uneeded request | ||
29 | - $http.get('/api/session').success(function (body) { | ||
30 | - _this.updateSessionInfos(body) | ||
31 | - if (cb) { | ||
32 | - if (this.logged) { | ||
33 | - cb(null) | ||
34 | - } else { | ||
35 | - cb(body) | ||
36 | - } | ||
37 | - } | ||
38 | - }) | ||
39 | - } else { | ||
40 | - console.warn("Unnecessary get() call") | ||
41 | - } | ||
42 | - }, | ||
43 | - connect: function (login, pass, cb) { | ||
44 | - _this = this | ||
45 | - $http.post('/api/session', { | ||
46 | - login: login, | ||
47 | - pass: pass | ||
48 | - }).success(function (body) { | ||
49 | - _this.updateSessionInfos(body) | ||
50 | - if (cb) { | ||
51 | - if (this.logged) { | ||
52 | - cb(null) | ||
53 | - } else { | ||
54 | - cb(body) | ||
55 | - } | ||
56 | - } | ||
57 | - }) | ||
58 | - }, | ||
59 | - disconnect: function () { | ||
60 | - this.updateSessionInfos(false) | ||
61 | - $http.delete('/api/session') | 1 | +angular.module('SessionsServ', []).service('SessionService', ['$http', 'EncryptService', |
2 | + function ($http, EncryptService) { | ||
3 | + a = { | ||
4 | + cur: false, | ||
5 | + status: 0, | ||
6 | + changeHandlers: [], | ||
7 | + onChange: function (fun) { | ||
8 | + this.changeHandlers.push(fun); | ||
9 | + }, | ||
10 | + triggerChange: function () { | ||
11 | + for (var fun in this.changeHandlers) { | ||
12 | + this.changeHandlers[fun](); | ||
13 | + } | ||
14 | + }, | ||
15 | + updateSessionInfos: function (data) { | ||
16 | + console.log("Connection:", data); | ||
17 | + if (typeof data === 'object') { | ||
18 | + this.cur = data; | ||
19 | + } else { | ||
20 | + this.cur = false; | ||
21 | + } | ||
22 | + this.triggerChange(); | ||
23 | + }, | ||
24 | + get: function (cb) { // Fetch infos if needed | ||
25 | + if (status === 0) { | ||
26 | + this.status = 1; // Fetching | ||
27 | + _this = this; | ||
28 | + // TODO Verify if cookies to prevent uneeded request | ||
29 | + $http.get('/api/session').success(function (body) { | ||
30 | + _this.updateSessionInfos(body); | ||
31 | + if (cb) { | ||
32 | + if (this.logged) { | ||
33 | + cb(null); | ||
34 | + } else { | ||
35 | + cb(body); | ||
36 | + } | ||
62 | } | 37 | } |
38 | + }); | ||
39 | + } else { | ||
40 | + console.warn("Unnecessary get() call"); | ||
63 | } | 41 | } |
64 | - a.get() | ||
65 | - return a | ||
66 | - } | ||
67 | -]) | ||
68 | \ No newline at end of file | 42 | \ No newline at end of file |
43 | + }, | ||
44 | + connect: function (login, pass, cb) { | ||
45 | + _this = this; | ||
46 | + data = JSON.stringify({ | ||
47 | + login: login, | ||
48 | + pass: pass | ||
49 | + }); | ||
50 | + EncryptService.encrypt(data, function (dataCrypt) { | ||
51 | + $http.post('/api/session', [dataCrypt]).success(function (body) { | ||
52 | + _this.updateSessionInfos(body); | ||
53 | + if (cb) { | ||
54 | + if (this.logged) { | ||
55 | + cb(null); | ||
56 | + } else { | ||
57 | + cb(body); | ||
58 | + } | ||
59 | + } | ||
60 | + }); | ||
61 | + }); | ||
62 | + }, | ||
63 | + disconnect: function () { | ||
64 | + this.updateSessionInfos(false); | ||
65 | + $http.delete('/api/session'); | ||
66 | + } | ||
67 | + }; | ||
68 | + a.get(); | ||
69 | + return a; | ||
70 | + } | ||
71 | +]); |
public/views/connect.html
1 | <div class="container"> | 1 | <div class="container"> |
2 | <h1>Se connecter</h1> | 2 | <h1>Se connecter</h1> |
3 | - <div class="alert alert-warning" role="alert"><strong>Faites attention !</strong> Ce site internet est encore en développement, les connexions ne sont pas sécurisées.<br/> | ||
4 | - Soyez sûr d'être sur un réseau sécurisé tel que celui de Polytech ou de votre box internet avant d'entrer votre mot de passe.</div> | ||
5 | <form> | 3 | <form> |
6 | <div class="form-group"> | 4 | <div class="form-group"> |
7 | <label for="login">Identifiant</label> | 5 | <label for="login">Identifiant</label> |
@@ -13,4 +11,4 @@ | @@ -13,4 +11,4 @@ | ||
13 | </div> | 11 | </div> |
14 | <button type="submit" class="btn btn-default" ng-click="connect.connect()">Se connecter</button> | 12 | <button type="submit" class="btn btn-default" ng-click="connect.connect()">Se connecter</button> |
15 | </form> | 13 | </form> |
16 | -</div> | ||
17 | \ No newline at end of file | 14 | \ No newline at end of file |
15 | +</div> |
public/views/index.html
@@ -11,7 +11,9 @@ | @@ -11,7 +11,9 @@ | ||
11 | <script src="libs/angular/angular.min.js"></script> | 11 | <script src="libs/angular/angular.min.js"></script> |
12 | <script src="libs/angular-route/angular-route.min.js"></script> | 12 | <script src="libs/angular-route/angular-route.min.js"></script> |
13 | <script src="libs/angular-bootstrap/ui-bootstrap.min.js"></script> | 13 | <script src="libs/angular-bootstrap/ui-bootstrap.min.js"></script> |
14 | + <script src="libs/jsencrypt/bin/jsencrypt.min.js"></script> | ||
14 | <script src="js/controllers/MembreCtrl.js"></script> | 15 | <script src="js/controllers/MembreCtrl.js"></script> |
16 | + <script src="js/services/EncryptServ.js"></script> | ||
15 | <script src="js/services/SessionServ.js"></script> | 17 | <script src="js/services/SessionServ.js"></script> |
16 | <script src="js/controllers/SessionCtrl.js"></script> | 18 | <script src="js/controllers/SessionCtrl.js"></script> |
17 | <script src="js/controllers/ConnectCtrl.js"></script> | 19 | <script src="js/controllers/ConnectCtrl.js"></script> |
@@ -41,4 +43,4 @@ | @@ -41,4 +43,4 @@ | ||
41 | <div ng-view></div> | 43 | <div ng-view></div> |
42 | </div> | 44 | </div> |
43 | </body> | 45 | </body> |
44 | -</html> | ||
45 | \ No newline at end of file | 46 | \ No newline at end of file |
47 | +</html> |