app.c 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. app.c - Application code to manage authentication
  3. */
  4. #include "esp.h"
  5. /*
  6. Common base run for every request.
  7. */
  8. static void commonBase(HttpStream *stream)
  9. {
  10. cchar *uri;
  11. if (!httpIsAuthenticated(stream)) {
  12. /*
  13. Access to certain pages are permitted without authentication so the user can login and logout.
  14. */
  15. uri = getUri();
  16. if (sstarts(uri, "/public/") || smatch(uri, "/user/login") || smatch(uri, "/user/logout")) {
  17. return;
  18. }
  19. feedback("error", "Access Denied. Login required.");
  20. redirect("/public/login.esp");
  21. }
  22. }
  23. /*
  24. Callback from httpLogin to verify credentials using the password defined in the database.
  25. */
  26. static bool verifyUser(HttpStream *stream, cchar *username, cchar *password)
  27. {
  28. HttpAuth *auth;
  29. HttpUser *user;
  30. HttpRx *rx;
  31. EdiRec *urec;
  32. rx = stream->rx;
  33. auth = rx->route->auth;
  34. if ((urec = findRec("user", sfmt("username == %s", username))) == 0) {
  35. httpLog(stream->trace, "auth.login.error", "error", "msg:Cannot verify user, username:%s", username);
  36. return 0;
  37. }
  38. if (!mprCheckPassword(password, getField(urec, "password"))) {
  39. httpLog(stream->trace, "auth.login.error", "error", "msg:Password failed to authenticate, username:%s", username);
  40. mprSleep(500);
  41. return 0;
  42. }
  43. /*
  44. Cache the user and define the user roles. Thereafter, the app can use "httpCanUser" to test if the user
  45. has the required abilities (defined by their roles) to perform a given request or operation.
  46. */
  47. if ((user = httpLookupUser(auth, username)) == 0) {
  48. user = httpAddUser(auth, username, 0, ediGetFieldValue(urec, "roles"));
  49. }
  50. /*
  51. Define this as the authenticated and authorized user for this session
  52. */
  53. httpSetConnUser(stream, user);
  54. httpLog(stream->trace, "auth.login.authenticated", "context", "msg:User authenticated, username:%s", username);
  55. return 1;
  56. }
  57. /*
  58. Dynamic module initialization
  59. If using with a static link, call this function from your main program after initializing ESP.
  60. */
  61. ESP_EXPORT int esp_app_login_database(HttpRoute *route)
  62. {
  63. /*
  64. Define a custom authentication verification callback for the "app" auth store.
  65. */
  66. httpSetAuthStoreVerifyByName("app", verifyUser);
  67. /*
  68. Define the common base which is called for all requests before the action function is invoked.
  69. This base will check if the client is authenticated.
  70. */
  71. espDefineBase(route, commonBase);
  72. return 0;
  73. }