Khóa API NodeJS

Cập nhật 29/2/16. Các ví dụ mã này đã được cập nhật để phản ánh 3. 0 bản phát hành tích hợp express-stormpath

Khi bạn xây dựng API REST, việc tạo cơ sở hạ tầng cần thiết để bảo mật API bằng khóa, mã thông báo OAuth và phạm vi có thể rất tẻ nhạt, rủi ro và tốn thời gian. May mắn thay, Stormpath vừa thêm tính năng quản lý khóa API vào gói express-stormpath của chúng tôi. Giờ đây, các nhà phát triển ứng dụng web và API sử dụng express. js có thể tạo và quản lý Khóa API và mã thông báo OAuth cũng như tra cứu và bảo mật tài khoản nhà phát triển – tất cả đều không cần mã OAuth tùy chỉnh

Những gì chúng tôi đang xây dựng

Bài đăng này sẽ hướng dẫn bạn cách xây dựng một ứng dụng cấp tốc cho phép bạn

  • Tạo một tài khoản mới (đăng ký) với email và mật khẩu
  • Đăng nhập vào tài khoản mới của bạn (đăng nhập) bằng email và mật khẩu
  • Hiển thị trang bảng điều khiển sau khi bạn đăng nhập, trang này chỉ có thể truy cập được đối với người dùng đã đăng ký
  • Tự động tạo và hiển thị Khóa API cho người dùng đã đăng nhập trên bảng điều khiển
  • Thực hiện cuộc gọi REST bằng xác thực Cơ bản
  • Tạo mã thông báo OAuth có phạm vi
  • Thực hiện cuộc gọi REST bằng xác thực Bearer
  • Cho phép người dùng đã đăng nhập đăng xuất khỏi tài khoản của họ (đăng xuất)

API tôi đã tạo là một API đơn giản. nó trả về thời tiết cho một thành phố được yêu cầu ở Fahrenheit

Trước khi chúng ta bắt đầu…

Lưu ý cấu trúc thư mục của kho lưu trữ github cho dự án này. Tất cả logic phía máy chủ (mà bài đăng này tập trung vào) sẽ có trong server.js

Đăng nhập

Đăng ký và đăng nhập người dùng được tích hợp vào express-stormpath và là nơi tốt để bắt đầu với bất kỳ ứng dụng nào

Khóa API NodeJS

Chúng ta hãy xem mã làm cho điều này xảy ra. Trước tiên, chúng tôi nhập các gói cần thiết (tất cả mã trong bài đăng này đi vào tệp nút gốc, trong trường hợp của tôi là /server.js)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

var express = require('express');

var máy chủ = express();

var đường bão = yêu cầu('express-stormpath');

 

// Bây giờ, chúng tôi thiết lập máy chủ để sử dụng Stormpath

máy chủ. sử dụng(đường bão. init(máy chủ, {

  ứng dụng. {

    href. quy trình. env['STORMPATH_APPLICATION_HREF']

  },

  web. {

    đăng nhập. {

      nextUri. '/dashboard',

    },

    oauth2. {

      client_credentials. {

        accessToken. {

          ttl. 3600

        }

      }

    }

  }

}));

 

Trường application trỏ Stormpath đến đúng ứng dụng cho dự án. Người dùng sẽ được trỏ đến nextUri sau khi đăng nhập hoặc tạo tài khoản. Đối với các trường Oauth, chúng ta sẽ quay lại những trường đó sau. Điều quan trọng là tránh lưu trữ Khóa API, Href ứng dụng và Khóa bí mật (được sử dụng cho phiên người dùng) ở dạng văn bản thuần túy trong mã của bạn. Thay vào đó, hãy xuất chúng dưới dạng biến môi trường và truy cập chúng trong máy chủ. js bằng cách thực hiện process.env['name_of_env_var']. Stormpath-express có khả năng tự đọc các biến môi trường, vì vậy việc xuất chúng sang hệ thống của bạn là đủ;

Sau khi người dùng truy cập trang web của chúng tôi (gốc của trang web hoặc '/'), chúng tôi cần chuyển hướng họ đến trang đăng nhập tùy chỉnh do Stormpath-express cung cấp, theo mặc định, trang này tồn tại ở /login

1

2

3

4

máy chủ. lấy('/', function(req, res) {

  res. chuyển hướng(302, ');

});

 

Bây giờ chúng ta đã hoàn thành việc đăng nhập và tạo tài khoản, hãy sử dụng Khóa API để bảo vệ API thời tiết của chúng ta

Tạo khóa API

Trước tiên, chúng ta cần cung cấp cho người dùng một khóa API để sử dụng. Bằng cách này, mọi điểm cuối REST đều được bảo vệ và chỉ những người dùng có Khóa API và Bí mật mới có thể truy cập được. Sau khi người dùng đăng nhập hoặc tạo tài khoản, họ sẽ chuyển trực tiếp đến bảng điều khiển ứng dụng, nơi Khóa API được tạo và hiển thị tự động

Khóa API NodeJS

Hãy xem mã trông như thế nào

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

máy chủ. lấy('/dashboard', stormpath.Yêu cầu đăng nhập, chức năng(req, res) {

  res. người dân địa phương. người dùng. getApiKeys(hàm(err, collectionResult) {

    if (kết quả thu thập. mặt hàng. độ dài === 0) {

      res. người dân địa phương. người dùng. createApiKey(hàm(err, apiKey) {

        res. người dân địa phương. apiKeyId = apiKey. id;

        res. người dân địa phương. apiKeySecret = apiKey. bí mật;

        res. người dân địa phương. tên người dùng = res. người dân địa phương. người dùng. tên người dùng;

        res. kết xuất('dashboard. ejs');

      });

    } else {

      kết quả bộ sưu tập. mỗi(chức năng(apiKey) {

        res. người dân địa phương. apiKeyId = apiKey. id;

        res. người dân địa phương. apiKeySecret = apiKey. bí mật;

        res. người dân địa phương. tên người dùng = res. người dân địa phương. người dùng. tên người dùng;

        res. kết xuất('dashboard. ejs');

      });

    }

  })

});

 

Bằng cách gọi cho res.locals.user.getApiKeys, chúng tôi yêu cầu Stormpath trả lại bộ sưu tập Khóa API của tài khoản. Trong câu lệnh if, chúng tôi kiểm tra xem tài khoản có bất kỳ Khóa API nào không. Nếu không, Stormpath sẽ tạo một cái và trả lại cho máy khách. Trong câu lệnh else, nơi Khóa API đã được tạo, Stormpath trả về Khóa API đầu tiên có sẵn

Thực hiện cuộc gọi REST với xác thực cơ bản

Bây giờ người dùng đã đăng nhập và có quyền truy cập bằng cách sử dụng Id và bí mật khóa API. Hãy để họ thực hiện lệnh gọi API

Khóa API NodeJS

Trong ứng dụng mẫu này, điểm cuối REST trả về một số dấu phẩy động, biểu thị thời tiết ở thành phố được yêu cầu. Ví dụ: nếu một yêu cầu GET được thực hiện tới /weather/London, một số dấu phẩy động có một chữ số sau dấu thập phân được trả về cho khách hàng đại diện cho thời tiết ở Luân Đôn. Chỉ có một điểm cuối có sẵn ở dạng /server.js)0, trong đó thành phố có thể là bất kỳ một trong bốn thành phố được cung cấp bởi các nút radio

Đầu tiên, khách hàng phải mã hóa khóa Base64. cặp bí mật và gửi cặp này đến máy chủ dưới dạng tiêu đề ủy quyền. trong góc cạnh. js, yêu cầu HTTP sẽ giống như thế này

1

2

3

4

5

6

7

8

9

10

11

$http({

  phương pháp. 'NHẬN',

  url. '/weather/' + $phạm vi.thành phố,

  tiêu đề. { 'Ủy quyền'. 'Basic ' + sharedProperties. getEncodedAuth() }

}). thành công(chức năng(dữ liệu, status, headers, config) {

  $phạm vi. nhiệt độ = dữ liệu + ';

  $phạm vi. myCity = $phạm vi. thành phố;

}). lỗi(hàm(dữ liệu, status, headers, config) {

  $cửa sổ. cảnh báo('Lỗi');

});

 

Trong yêu cầu HTTP này, chúng tôi chỉ định thành phố mong muốn trong url. /server.js)1 và thêm khóa API được mã hóa Base64 của chúng tôi làm tiêu đề ủy quyền

Bây giờ hãy xem điều gì xảy ra ở phía máy chủ, nơi yêu cầu này được xử lý

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

máy chủ. nhận('/weather/. thành phố', đường đi bão. Yêu cầu xác thực api, chức năng(req, res) {

  chức năng lấy Thời tiết() {

    bảng điều khiển. log('Nhận thông tin thời tiết cho ' + req.tham số. thành phố);

    var url = " 'ttp://api.openweathermap.org/data/2.5/weather?q=' + yêu cầu. tham số. thành phố;

    var dữ liệu = '';

 

    http. lấy(url, hàm(myRes) {

      myRes. bật('dữ liệu', function(chunk) {

        dữ liệu += đoạn;

      });

 

      myRes. bật('kết thúc', function() {

        gọi lại(dữ liệu);

      });

    }). bật('lỗi', function() {

      bảng điều khiển. log('Lỗi nhận dữ liệu. ');

    });

  }

 

  hàm gọi lại(Dữ liệu cuối cùng) {

    var json = JSON.phân tích cú pháp(Dữ liệu cuối cùng);

 

    // Chuyển đổi sang Chiều cao.

    var giá vé = Toán.vòng(((( . parseFloat(json.chính. nhiệt độ) - 273. 15) * 1. 8) + 32) * 10) / 10;

    res. trạng thái(200). json(giá vé);

  }

 

  nếu (yêu cầu. tiêu đề. ủy quyền. indexOf('Cơ bản') ! == 0) {

    return res. trạng thái(403). kết thúc();

  }

 

  getWeather();

});

 

Đầu tiên, hãy chú ý cuộc gọi /server.js)2 trước chức năng gọi lại của tuyến đường của chúng tôi. Hàm này xác minh rằng thông tin đăng nhập ủy quyền được gửi qua là hợp lệ. Nếu không, máy chủ sẽ trả về lỗi /server.js)3. Giả sử thông tin đăng nhập là chính xác, máy chủ sau đó được phép trả về thời tiết của thành phố mong muốn

Đây là cách yêu cầu tương tự có thể được thực hiện với CURL

1

2

$ curl -- người dùng '[API_KEY]. [API_SECRET]' http. //máy chủ cục bộ. 8080/thời tiết/London

 

Nếu xác thực thành công, bạn sẽ nhận được một số dấu phẩy động đại diện cho thời tiết ở London. Nếu không, bạn sẽ thấy. /server.js)4

Tạo mã thông báo OAuth với phạm vi

Xác thực cơ bản được chấp nhận đối với một số trường hợp sử dụng, nhưng chúng tôi thực sự khuyên bạn nên sử dụng OAuth nếu bảo mật là quan trọng đối với API của bạn. Bằng cách sử dụng OAuth, việc gửi yêu cầu tới các điểm cuối được bảo vệ sẽ không làm lộ Id và bí mật khóa API. Nó cũng cung cấp cho nhà phát triển khả năng chỉ cấp quyền truy cập vào các phạm vi nhất định của điểm cuối mà người dùng đang cố truy cập. Điều này được so sánh với việc xác thực bằng các khóa API, cho phép truy cập vào toàn bộ điểm cuối

Khóa API NodeJS

Bằng cách kiểm tra các thành phố mong muốn và nhấp vào /server.js)5, người dùng sẽ nhận được mã thông báo hiện có thể được sử dụng để nhắm mục tiêu điểm cuối REST. Chính xác thì điều gì đã xảy ra ở phía máy chủ để tạo Mã thông báo Oauth này?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

máy chủ. sử dụng(đường bão. init(máy chủ, {

  ứng dụng. {

    href. quy trình. env['STORMPATH_APPLICATION_HREF']

  },

  web. {

    đăng nhập. {

      nextUri. '/dashboard',

    },

    oauth2. {

      client_credentials. {

        accessToken. {

          ttl. 3600

        }

      }

    }

  }

}));

 

Với điều này, yêu cầu /server.js)6 được gửi tới URL đó sẽ kiểm tra thông tin đăng nhập Khóa API và trả lại Mã thông báo có giá trị trong 1 giờ (theo mặc định). Yêu cầu /server.js)6 này cũng cần phải có tham số biểu mẫu “grant_type” với giá trị được đặt làm phạm vi được yêu cầu. Đây là yêu cầu trong góc. js

1

2

3

4

5

6

7

8

9

10

11

12

13

myData = $. param({grant_type. "client_credentials", phạm vi. scopeData});

$http({

  phương pháp. 'POST',

  url. '/oauth/token',

  tiêu đề. { 'Ủy quyền'. 'Basic ' + sharedProperties. getEncodedAuth(), ' . : 'application/x-www-form-urlencoded' },

  dữ liệu . Dữ liệu của tôi

}). thành công(chức năng(dữ liệu, status, headers, config) {

  var oauthToken = dữ liệu.access_token;

  $phạm vi. oauthToken = oauthToken;

}). lỗi(hàm(dữ liệu, status, headers, config) {

  $cửa sổ. cảnh báo('Lỗi');

});

 

Thực hiện cuộc gọi REST bằng mã thông báo OAuth

Để đạt được điểm cuối REST bằng Oauth, chúng tôi phải gửi mã thông báo của mình đến điểm cuối /server.js)0 bằng cách sử dụng xác thực Bearer

1

2

3

4

5

6

7

8

9

10

11

$http({

  phương pháp. 'NHẬN',

  url. '/weather/' + $phạm vi.thành phố,

  tiêu đề. { 'Ủy quyền'. 'Bearer ' + sharedProperties. getOauthToken() }

}). thành công(chức năng(dữ liệu, status, headers, config) {

  $phạm vi. nhiệt độ = dữ liệu + ';

  $phạm vi. myCity = $phạm vi. thành phố;

}). lỗi(hàm(dữ liệu, status, headers, config) {

  $cửa sổ. cảnh báo('Quyền bị từ chối. ');

});

 

Bây giờ, về phía máy chủ, chúng tôi có thể thêm logic để xác thực Bearer và phân tích phạm vi được yêu cầu của chúng tôi

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

máy chủ. nhận('/weather/. thành phố', đường đi bão. Yêu cầu xác thực api, chức năng(req, res) {

  nếu (yêu cầu. tiêu đề. ủy quyền. indexOf('Cơ bản') === 0) {

    getWeather();

  } else if (req.tiêu đề. ủy quyền. indexOf('Người mang') === 0) {

    var requestedCity = req.tham số. thành phố. thay thế( / \s+/g, '');

    nếu (res. người dân địa phương. quyền. indexOf(requestedCity) >= 0) {

      lấy Thời tiết();

    } else {

      res. trạng thái(403). kết thúc();

    }

  } else {

    res. trạng thái(403). kết thúc();

  }

 

  chức năng lấy Thời tiết() {

    bảng điều khiển. log('Nhận thông tin thời tiết cho ' + req.tham số. thành phố);

    var url = 'http. //api. bản đồ thời tiết mở. tổ chức/dữ liệu/2. 5/thời tiết?q=' + yêu cầu. tham số. thành phố;

    var dữ liệu = '';

 

    http. lấy(url, hàm(myRes) {

      myRes. bật('dữ liệu', function(chunk) {

        dữ liệu += đoạn;

      });

      myRes. bật('kết thúc', function() {

        gọi lại(dữ liệu);

      });

    }). bật('lỗi', function() {

      bảng điều khiển. log('Lỗi nhận dữ liệu. ');

    });

  }

 

  hàm gọi lại(Dữ liệu cuối cùng) {

    var json = JSON.phân tích cú pháp(Dữ liệu cuối cùng);

    bảng điều khiển. log(json. chính. nhiệt độ);

 

    // Chuyển đổi sang Chiều cao.

    var giá vé = Toán.vòng(((( . parseFloat(json.chính. nhiệt độ) - 273. 15) * 1. 8) + 32) * 10) / 10;

    res. trạng thái(200). json(giá vé);

  }

});

 

Các phạm vi được yêu cầu sống bên trong đối tượng /server.js)9 và chúng tôi có thể tìm kiếm nó để xem liệu thành phố mà chúng tôi muốn có thời tiết có được phép đối với chúng tôi hay không. Nếu vậy, máy chủ sẽ tiến hành trả lại thời tiết; . So với lỗi application1, nghĩa là yêu cầu trái phép, thì lỗi application0 nghĩa là yêu cầu bị cấm

Luân Đôn là một phần của phạm vi trong Mã thông báo Oauth nên việc nắm bắt thời tiết của nó không có vấn đề gì

Khóa API NodeJS

Mặt khác, Berlin thì không, vì vậy thời tiết không được đưa ra và thay vào đó, một lỗi được trả về

Khóa API NodeJS

Phần kết luận

Nút. js và gói Stormpath-express giúp dễ dàng tạo và quản lý xác thực dựa trên Khóa API trong ứng dụng web hoặc API của bạn. Nếu bạn muốn xem thêm mã và thậm chí tự chạy ứng dụng này, hãy xem mã nguồn và cho chúng tôi biết suy nghĩ của bạn

Khóa API trong nút js là gì?

Sử dụng khóa API có lợi thế nếu bạn muốn đặt giới hạn hoặc theo dõi tần suất một người dùng cụ thể sử dụng API . Bằng cách sử dụng các khóa API, người dùng không cần phải lo lắng về xác thực đa yếu tố với tên người dùng và mật khẩu của họ. Người dùng API của bạn sẽ có thể tự động tìm nạp dữ liệu trên ứng dụng.

Ví dụ về khóa API là gì?

Khóa API là mã định danh duy nhất được sử dụng để kết nối hoặc thực hiện lệnh gọi API . API là viết tắt của giao diện lập trình ứng dụng. API được sử dụng cho các ứng dụng phần mềm để gửi và nhận dữ liệu. API cũng có thể kết nối chương trình này với chương trình khác để chia sẻ chức năng.

Làm cách nào để tạo khóa API trong JavaScript?

Trong phần Tạo khóa, hãy đặt tên cho khóa API dành riêng cho dự án của bạn, sau đó nhấp vào nút Tạo . Điều này sẽ đưa bạn đến một trang liệt kê bất kỳ khóa nào bạn đã tạo. Chúng sẽ trông giống như một chuỗi ngẫu nhiên gồm 32 ký tự.

Có thể cung cấp khóa API không?

Khi bạn sử dụng khóa API trong các ứng dụng Google Cloud Platform (GCP), hãy cẩn thận để giữ an toàn cho chúng . Tiết lộ công khai thông tin đăng nhập của bạn có thể dẫn đến việc tài khoản của bạn bị xâm phạm, điều này có thể dẫn đến các khoản phí không mong muốn trên tài khoản của bạn.