mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-27 16:24:07 +02:00
auth sessions
This commit is contained in:
parent
81ec1a6469
commit
3978ed8204
@ -21,6 +21,10 @@ void route_get_products_all(HttpCtx* ctx);
|
||||
void route_post_user_register(HttpCtx* ctx);
|
||||
|
||||
void route_post_auth_login(HttpCtx* ctx);
|
||||
void route_post_auth_logout(HttpCtx* ctx);
|
||||
|
||||
const Session* header_session(HttpCtx* ctx);
|
||||
const Session* middleware_session(HttpCtx* ctx);
|
||||
|
||||
#define RESPOND(HTTP_CTX, STATUS, MIME_TYPE, ...) \
|
||||
{ \
|
||||
@ -47,8 +51,7 @@ void route_post_auth_login(HttpCtx* ctx);
|
||||
#define RESPOND_SERVER_ERROR(HTTP_CTX) \
|
||||
RESPOND_JSON(HTTP_CTX, 500, "{\"ok\":false,\"msg\":\"server error\"}")
|
||||
|
||||
__attribute__((unused))
|
||||
static inline void ___include_user(void)
|
||||
__attribute__((unused)) static inline void ___include_user(void)
|
||||
{
|
||||
RESPOND((HttpCtx*)0, 200, "text/html", "")
|
||||
}
|
||||
|
@ -41,13 +41,46 @@ void route_post_auth_login(HttpCtx* ctx)
|
||||
goto l2_return;
|
||||
}
|
||||
|
||||
session_vec_remove_user_id(&cx->sessions, user.id);
|
||||
char* token = str_random(64);
|
||||
session_vec_add(&cx->sessions, user.id, token);
|
||||
sessions_remove(&cx->sessions, user.id);
|
||||
Session* session = sessions_add(&cx->sessions, user.id);
|
||||
|
||||
RESPOND_JSON(ctx, 200, "{\"ok\":true,\"token\":\"%s\"}", token);
|
||||
RESPOND_JSON(ctx, 200, "{\"ok\":true,\"token\":\"%s\"}", session->token);
|
||||
l2_return:
|
||||
user_destroy(&user);
|
||||
l0_return:
|
||||
auth_login_req_destroy(&req);
|
||||
}
|
||||
|
||||
void route_post_auth_logout(HttpCtx* ctx)
|
||||
{
|
||||
Cx* cx = http_ctx_user_ctx(ctx);
|
||||
const Session* session = header_session(ctx);
|
||||
if (!session) {
|
||||
RESPOND_JSON(ctx, 200, "{\"ok\":true}");
|
||||
return;
|
||||
}
|
||||
sessions_remove(&cx->sessions, session->user_id);
|
||||
RESPOND_JSON(ctx, 200, "{\"ok\":true}");
|
||||
}
|
||||
|
||||
const Session* header_session(HttpCtx* ctx)
|
||||
{
|
||||
Cx* cx = http_ctx_user_ctx(ctx);
|
||||
if (!http_ctx_req_headers_has(ctx, "Session-Token")) {
|
||||
return NULL;
|
||||
}
|
||||
const char* token = http_ctx_req_headers_get(ctx, "Session-Token");
|
||||
// session expiration should be handled here
|
||||
return sessions_find(&cx->sessions, token);
|
||||
}
|
||||
|
||||
// Returns NULL AND responds if no valid session is found.
|
||||
const Session* middleware_session(HttpCtx* ctx)
|
||||
{
|
||||
const Session* session = header_session(ctx);
|
||||
if (!session) {
|
||||
RESPOND_JSON(ctx, 200, "{\"ok\":false,\"msg\":\"unauthorized\"}");
|
||||
return NULL;
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "http_server.h"
|
||||
#include "http_server_internal.h"
|
||||
#include "str_util.h"
|
||||
#include <ctype.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
@ -358,10 +359,19 @@ static inline int parse_header(
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (method_str.len >= 8) {
|
||||
fprintf(stderr, "error: malformed http method\n");
|
||||
return -1;
|
||||
}
|
||||
char normalized_method[8] = "";
|
||||
for (size_t i = 0; i < method_str.len; ++i) {
|
||||
normalized_method[i] = (char)toupper(method_str.ptr[i]);
|
||||
}
|
||||
|
||||
Method method;
|
||||
if (strncmp(method_str.ptr, "GET", method_str.len) == 0) {
|
||||
if (strncmp(normalized_method, "GET", method_str.len) == 0) {
|
||||
method = Method_GET;
|
||||
} else if (strncmp(method_str.ptr, "POST", method_str.len) == 0) {
|
||||
} else if (strncmp(normalized_method, "POST", method_str.len) == 0) {
|
||||
method = Method_POST;
|
||||
} else {
|
||||
fprintf(stderr, "error: unrecognized http method '%.*s'\n",
|
||||
|
@ -46,6 +46,7 @@ int main(void)
|
||||
|
||||
http_server_post(server, "/api/users/register", route_post_user_register);
|
||||
http_server_post(server, "/api/auth/login", route_post_auth_login);
|
||||
http_server_post(server, "/api/auth/logout", route_post_auth_logout);
|
||||
|
||||
http_server_get(server, "/", route_get_index);
|
||||
http_server_post(server, "/set_number", route_post_set_number);
|
||||
|
@ -1,28 +1,54 @@
|
||||
#include "session.h"
|
||||
#include "str_util.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void session_construct(Session* session, int64_t user_id)
|
||||
{
|
||||
char* token = str_random(64);
|
||||
size_t token_hash = str_fast_hash(token);
|
||||
*session = (Session) { user_id, token, token_hash };
|
||||
}
|
||||
|
||||
void session_destroy(Session* session)
|
||||
{
|
||||
free(session->token);
|
||||
*session = (Session) {
|
||||
.user_id = 0,
|
||||
.token = NULL,
|
||||
.token_hash = 0,
|
||||
};
|
||||
}
|
||||
|
||||
void session_vec_remove_user_id(SessionVec* vec, int64_t user_id)
|
||||
void sessions_remove(SessionVec* vec, int64_t user_id)
|
||||
{
|
||||
for (size_t i = 0; i < vec->size; ++i) {
|
||||
if (vec->data[i].user_id == user_id) {
|
||||
session_destroy(&vec->data[i]);
|
||||
vec->data[i] = (Session) { 0, NULL };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void session_vec_add(SessionVec* vec, int64_t user_id, char* token)
|
||||
Session* sessions_add(SessionVec* vec, int64_t user_id)
|
||||
{
|
||||
for (size_t i = 0; i < vec->size; ++i) {
|
||||
if (vec->data[i].user_id == 0) {
|
||||
vec->data[i] = (Session) { user_id, token };
|
||||
return;
|
||||
session_construct(&vec->data[i], user_id);
|
||||
return &vec->data[i];
|
||||
}
|
||||
}
|
||||
session_vec_push(vec, (Session) { user_id, token });
|
||||
Session session;
|
||||
session_construct(&session, user_id);
|
||||
session_vec_push(vec, session);
|
||||
return &vec->data[vec->size - 1];
|
||||
}
|
||||
|
||||
const Session* sessions_find(SessionVec* vec, const char* token)
|
||||
{
|
||||
size_t token_hash = str_fast_hash(token);
|
||||
for (size_t i = 0; i < vec->size; ++i) {
|
||||
if (vec->data[i].token_hash == token_hash) {
|
||||
return &vec->data[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -6,11 +6,14 @@
|
||||
typedef struct {
|
||||
int64_t user_id;
|
||||
char* token;
|
||||
size_t token_hash;
|
||||
} Session;
|
||||
|
||||
void session_construct(Session* session, int64_t user_id);
|
||||
void session_destroy(Session* session);
|
||||
|
||||
DEFINE_VEC(Session, SessionVec, session_vec, 16)
|
||||
|
||||
void session_vec_remove_user_id(SessionVec* vec, int64_t user_id);
|
||||
void session_vec_add(SessionVec* vec, int64_t user_id, char* token);
|
||||
void sessions_remove(SessionVec* vec, int64_t user_id);
|
||||
Session* sessions_add(SessionVec* vec, int64_t user_id);
|
||||
const Session* sessions_find(SessionVec* vec, const char* token);
|
||||
|
@ -164,6 +164,85 @@ bool str_hash_equal(const char* hash, const char* input)
|
||||
return hashdata_is_equal(data, input);
|
||||
}
|
||||
|
||||
static inline uint64_t chibihash64__load32le(const uint8_t* p)
|
||||
{
|
||||
return (uint64_t)p[0] << 0 | (uint64_t)p[1] << 8 | (uint64_t)p[2] << 16
|
||||
| (uint64_t)p[3] << 24;
|
||||
}
|
||||
static inline uint64_t chibihash64__load64le(const uint8_t* p)
|
||||
{
|
||||
return chibihash64__load32le(p) | (chibihash64__load32le(p + 4) << 32);
|
||||
}
|
||||
static inline uint64_t chibihash64__rotl(uint64_t x, int n)
|
||||
{
|
||||
return (x << n) | (x >> (-n & 63));
|
||||
}
|
||||
|
||||
static inline uint64_t chibihash64(
|
||||
const void* keyIn, ptrdiff_t len, uint64_t seed)
|
||||
{
|
||||
const uint8_t* p = (const uint8_t*)keyIn;
|
||||
ptrdiff_t l = len;
|
||||
|
||||
const uint64_t K = UINT64_C(0x2B7E151628AED2A7); // digits of e
|
||||
uint64_t seed2
|
||||
= chibihash64__rotl(seed - K, 15) + chibihash64__rotl(seed - K, 47);
|
||||
uint64_t h[4] = { seed, seed + K, seed2, seed2 + (K * K ^ K) };
|
||||
|
||||
// depending on your system unrolling might (or might not) make things
|
||||
// a tad bit faster on large strings. on my system, it actually makes
|
||||
// things slower.
|
||||
// generally speaking, the cost of bigger code size is usually not
|
||||
// worth the trade-off since larger code-size will hinder inlinability
|
||||
// but depending on your needs, you may want to uncomment the pragma
|
||||
// below to unroll the loop.
|
||||
// #pragma GCC unroll 2
|
||||
for (; l >= 32; l -= 32) {
|
||||
for (int i = 0; i < 4; ++i, p += 8) {
|
||||
uint64_t stripe = chibihash64__load64le(p);
|
||||
h[i] = (stripe + h[i]) * K;
|
||||
h[(i + 1) & 3] += chibihash64__rotl(stripe, 27);
|
||||
}
|
||||
}
|
||||
|
||||
for (; l >= 8; l -= 8, p += 8) {
|
||||
h[0] ^= chibihash64__load32le(p + 0);
|
||||
h[0] *= K;
|
||||
h[1] ^= chibihash64__load32le(p + 4);
|
||||
h[1] *= K;
|
||||
}
|
||||
|
||||
if (l >= 4) {
|
||||
h[2] ^= chibihash64__load32le(p);
|
||||
h[3] ^= chibihash64__load32le(p + l - 4);
|
||||
} else if (l > 0) {
|
||||
h[2] ^= p[0];
|
||||
h[3] ^= p[l / 2] | ((uint64_t)p[l - 1] << 8);
|
||||
}
|
||||
|
||||
h[0] += chibihash64__rotl(h[2] * K, 31) ^ (h[2] >> 31);
|
||||
h[1] += chibihash64__rotl(h[3] * K, 31) ^ (h[3] >> 31);
|
||||
h[0] *= K;
|
||||
h[0] ^= h[0] >> 31;
|
||||
h[1] += h[0];
|
||||
|
||||
uint64_t x = (uint64_t)len * K;
|
||||
x ^= chibihash64__rotl(x, 29);
|
||||
x += seed;
|
||||
x ^= h[1];
|
||||
|
||||
x ^= chibihash64__rotl(x, 15) ^ chibihash64__rotl(x, 42);
|
||||
x *= K;
|
||||
x ^= chibihash64__rotl(x, 13) ^ chibihash64__rotl(x, 31);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t str_fast_hash(const char* input)
|
||||
{
|
||||
return chibihash64(input, sizeof(char*), 0x80085);
|
||||
}
|
||||
|
||||
char* str_random(size_t length)
|
||||
{
|
||||
char* string = calloc(length + 1, sizeof(char));
|
||||
|
@ -38,6 +38,8 @@ DEFINE_VEC(char*, RawStrVec, rawstr_vec, 8)
|
||||
char* str_hash(const char* input);
|
||||
bool str_hash_equal(const char* hash, const char* input);
|
||||
|
||||
uint64_t str_fast_hash(const char* input);
|
||||
|
||||
char* str_random(size_t length);
|
||||
|
||||
void str_util_test(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user