首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HapiJS用户会话管理

HapiJS用户会话管理
EN

Stack Overflow用户
提问于 2021-06-02 18:51:14
回答 1查看 154关注 0票数 0

下面的代码来自HapiJS文档,它描述了如何使用@hapi/cookie插件来使用会话和cookie。

代码语言:javascript
复制
'use strict';

const Hapi = require('@hapi/hapi');


const internals = {};


// Simulate database for demo

internals.users = [
    {
        id: 1,
        name: 'john',
        password: 'password',
    },
];


internals.renderHtml = {
    login: (message) => {

        return `
    <html><head><title>Login page</title></head><body>
    ${message ? '<h3>' + message + '</h3><br></a>' : ''}
    <form method="post" action="/login">
      Username: <input type="text" name="username"><br>
      Password: <input type="password" name="password"><br></a>
    <input type="submit" value="Login"></form>
    </body></html>
      `;
    },
    home: (name) => {

        return `
    <html><head><title>Login page</title></head><body>
    <h3>Welcome ${name}! You are logged in!</h3>
    <form method="get" action="/logout">
      <input type="submit" value="Logout">
    </form>
    </body></html>
      `;
    }
};


internals.server = async function () {

    const server = Hapi.server({ port: 8000 });

    await server.register(require('@hapi/cookie'));

    server.auth.strategy('session', 'cookie', {

        cookie: {
            name: 'sid-example',

            // Don't forget to change it to your own secret password!
            password: 'password-should-be-32-characters',

            // For working via HTTP in localhost
            isSecure: false
        },

        redirectTo: '/login',

        validateFunc: async (request, session) => {

            const account = internals.users.find((user) => (user.id === session.id));

            if (!account) {
                // Must return { valid: false } for invalid cookies
                return { valid: false };
            }

            return { valid: true, credentials: account };
        }
    });

    server.auth.default('session');

    server.route([
        {
            method: 'GET',
            path: '/',
            options: {
                handler: (request, h) => {

                    return internals.renderHtml.home(request.auth.credentials.name);
                }
            }
        },
        {
            method: 'GET',
            path: '/login',
            options: {
                auth: {
                    mode: 'try'
                },
                plugins: {
                    'hapi-auth-cookie': {
                        redirectTo: false
                    }
                },
                handler: async (request, h) => {

                    if (request.auth.isAuthenticated) {
                        return h.redirect('/');
                    }

                    return internals.renderHtml.login();
                }
            }
        },
        {
            method: 'POST',
            path: '/login',
            options: {
                auth: {
                    mode: 'try'
                },
                handler: async (request, h) => {

                    const { username, password } = request.payload;
                    if (!username || !password) {
                        return internals.renderHtml.login('Missing username or password');
                    }

                    // Try to find user with given credentials

                    const account = internals.users.find(
                        (user) => user.name === username && user.password === password
                    );

                    if (!account) {
                        return internals.renderHtml.login('Invalid username or password');
                    }

                    request.cookieAuth.set({ id: account.id });
                    return h.redirect('/');
                }
            }
        },
        {
            method: 'GET',
            path: '/logout',
            options: {
                handler: (request, h) => {

                    request.cookieAuth.clear();
                    return h.redirect('/');
                }
            }
        }
    ]);

    await server.start();
    console.log(`Server started at: ${server.info.uri}`);
};


internals.start = async function() {

    try {
        await internals.server();
    }
    catch (err) {
        console.error(err.stack);
        process.exit(1);
    }
};

internals.start();

我的问题是:在POST登录路由中,在用户成功登录后,request.cookieAuth.set({ id: account.id });是否将{id:account.id}保存在内存中(缓存)并将其作为cookie发送给客户端?还是这里什么都没救?类似地,request.cookieAuth.clear();是否从内存和客户端清除会话??

EN

回答 1

Stack Overflow用户

发布于 2022-04-13 21:02:12

Hapi.js有自己的内存系统,但您也可以选择使用一些自定义的东西,比如Redis或其他商店。

我使用Hapi的商店,它在单个服务器实例中运行良好。如果您计划拥有一个服务器实例集群,则需要将存储此类数据的数据卸载到像Redis这样的后端存储区,否则如果连接不粘稠,它们将在每个请求中负载平衡,而且如果用户碰到没有缓存会话的服务器实例,则该用户似乎已被注销。使用同步后端缓存,所有服务器实例共享该缓存数据并保持同步。

这是我管理事情的方法。我会为会话密钥生成一个唯一的UUID,因为用户id是非常明显的。

代码语言:javascript
复制
export class AuthCookieData implements IAuthCookieData {
  sid: string
  constructor(data: IAuthCookieData) {
    this.sid = data.sid;
  }
}

export class AuthCookie {

  /**
   *  accepts one parameter: account
   *  account: the user account to register as {username:'username', password:'password', email: 'user@email.com'}
   *  returns: Promise with new account
   */
  static async setCookie(request: Hapi.Request, userProfile: UserProfile): Promise<void> {
      var sid = uuid.v4();
      await request.server.app['cache'].set(sid, userProfile, 0);
      request['cookieAuth'].set(new AuthCookieData({ sid: sid }));
    }
  }

  static async sessionCacheFunction(request: Hapi.Request, session: AuthCookieData) {

    var userProfile: UserProfile = await request.server.app['cache'].get(session.sid);
    if (!userProfile) {
      return { valid: false };
    } else {
      return { valid: true, credentials: userProfile };
    }

  }
}
代码语言:javascript
复制
const handler:Hapi.Lifecycle.Method = async (request: Hapi.Request, h: Hapi.ResponseToolkit) => {
  if (request.auth.isAuthenticated) {
    return request.auth.credentials;
  }
  const userProfile: UserProfile = await UserUtility.login(<ILogin>request.payload);
  if (!userProfile) {
    return Boom.badRequest('Could not authenticate.  Username or password is invalid.');
  }
  AuthCookie.setCookie(request, userProfile);
  return profile;
};
代码语言:javascript
复制
server.auth.strategy('session', 'cookie', {    
  cookie: {
    name: 'sid',
    password: Configuration.auth.password,
    isSecure: false,
    clearInvalid: true
  },
  validateFunc: AuthCookie.sessionCacheFunction
});  
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67810882

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档