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 @@ |
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 | 1 | var membres = require('../controllers/membres'); |
2 | 2 | var sessions = require('../controllers/sessions'); |
3 | +var decrypt = require('../controllers/decrypt'); | |
3 | 4 | var express = require('express'); |
4 | 5 | |
5 | -var api = express() | |
6 | +var api = express(); | |
6 | 7 | |
7 | 8 | // Sessions |
8 | 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 | 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 | 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 | 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 | 63 | // Membres |
61 | 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 | 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 | 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 | 100 | \ No newline at end of file |
101 | +module.exports = api; | ... | ... |
bower.json
package.json
... | ... | @@ -0,0 +1 @@ |
1 | +Même pas en rêve ! | ... | ... |
public/js/app.js
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 | 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 @@ |
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 | 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 | 1 | <div class="container"> |
2 | 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 | 3 | <form> |
6 | 4 | <div class="form-group"> |
7 | 5 | <label for="login">Identifiant</label> |
... | ... | @@ -13,4 +11,4 @@ |
13 | 11 | </div> |
14 | 12 | <button type="submit" class="btn btn-default" ng-click="connect.connect()">Se connecter</button> |
15 | 13 | </form> |
16 | -</div> | |
17 | 14 | \ No newline at end of file |
15 | +</div> | ... | ... |
public/views/index.html
... | ... | @@ -11,7 +11,9 @@ |
11 | 11 | <script src="libs/angular/angular.min.js"></script> |
12 | 12 | <script src="libs/angular-route/angular-route.min.js"></script> |
13 | 13 | <script src="libs/angular-bootstrap/ui-bootstrap.min.js"></script> |
14 | + <script src="libs/jsencrypt/bin/jsencrypt.min.js"></script> | |
14 | 15 | <script src="js/controllers/MembreCtrl.js"></script> |
16 | + <script src="js/services/EncryptServ.js"></script> | |
15 | 17 | <script src="js/services/SessionServ.js"></script> |
16 | 18 | <script src="js/controllers/SessionCtrl.js"></script> |
17 | 19 | <script src="js/controllers/ConnectCtrl.js"></script> |
... | ... | @@ -41,4 +43,4 @@ |
41 | 43 | <div ng-view></div> |
42 | 44 | </div> |
43 | 45 | </body> |
44 | -</html> | |
45 | 46 | \ No newline at end of file |
47 | +</html> | ... | ... |