我在服务器端的NodeJS 12 Express 4和客户端的Angular 8 SPA中构建Web应用程序。
服务器端登录路由用于运行护照认证策略。用户通过身份验证后,将返回用户对象。将创建一个JWT并用用户对象签名。
jwt = jwtCtrl.generateJwt(user);
然后将JWT放置在cookie中,并将 httpOnly 标志设置为true。 Cookie存储在浏览器中,并将在所有HTTP请求中进行身份验证和授权,并发送回服务器。
res.cookie('jwt', jwt, options.jwtCookieOptions);
如果我的理解正确,则 httpOnly 标志必须为 true ,以防止XSS攻击。 httpOnly标志可防止任何客户端javascript访问cookie。 Cookie包含身份验证令牌,因此客户端不应访问它。
但是,Angular SPA确实需要访问某些用户属性,例如电子邮件地址和访问级别。
我创建了SECOND cookie来发送用户详细信息,而不是公开'jwt'cookie。 “用户” cookie的httpOnly设置为false,以便客户端可以访问。
通过这种方式,“ jwt” cookie被发送回服务器进行身份验证,并受到httpOnly的保护,而SPA仅将“用户” cookie用于显示目的,例如,如果用户具有管理员访问权限级别。所有身份验证和查询将仅基于'jwt'cookie。
问题:
以下示例中的代码可以正常工作,以便在快递服务器中创建两个cookie并重定向回有角度的spa客户端。这两个Cookie的maxAge值相同。我只是想知道以这种方式发送两个不同的cookie是否是#1良好做法#2建议#3可持续的。还是通过这种或更好的方法实现目标存在一些缺陷?请注意,由于服务器正在重定向回客户端,因此我故意不在标头Authorization Bearer中发送JWT。另外,httpOnly似乎是在客户端上存储JWT的更好方法。
// Set options
loginCtrl.setCookieOptions = () => {
const COOKIE_MAX_AGE_MINS = Number(process.env.COOKIE_MAX_AGE_MINS) ? Number(process.env.COOKIE_MAX_AGE_MINS) : 480;
/**
* JWT cookie options
* Cookie to store JWT authentication token
* httpOnly set to true for web server access only
*
*/
const jwtCookieOptions = {
maxAge: COOKIE_MAX_AGE_MINS * 1000 * 60,
signed: true,
secureCookie: true,
sameSite: true,
// Prevent client side javascript access, this cookie contains auth token
httpOnly: true,
// Attach cookie to all requests in this path
path: '/api'
}
/**
* User cookie options
* Cookie to store user properties
* httpOnly set to false to allow client access
* The user cookie contains email address and access level only
*
*/
const userCookieOptions = {
maxAge: COOKIE_MAX_AGE_MINS * 1000 * 60,
signed: false,
secureCookie: true,
sameSite: true,
// Allow client side javascript access, this cookie does not contain auth token
httpOnly: false,
// Attach cookie to all requests in this path
path: '/'
}
return {
jwtCookieOptions: jwtCookieOptions,
userCookieOptions: userCookieOptions
}
}
router.post('/login', (req, res, next) => {
/* Authentication logic to set user... */
passport.authenticate('local', function (err, user, info) {
/* AUTHENTICATION SUCCESS */
if (user) {
// Generate JWT token
let jwt;
jwt = jwtCtrl.generateJwt(user);
// Set cookie options
const options = loginCtrl.setCookieOptions();
// Store JWT in a cookie to be sent back to server for authentication in every request
// Since it contains auth jwt token this cookie is accessible to server only
res.cookie('jwt', jwt, options.jwtCookieOptions);
// Store user properties in a cookie to be read by client side app
res.cookie('user',
JSON.stringify({ EmailAddress: user.EmailAddress, AccessLevel: user.AccessLevel }),
options.userCookieOptions
);
// Redirect to the Angular SPA client
return res.redirect(302, 'http://angular-spa-client.com/');
}
})(req, res);
});