如何在单页应用程序中使用 ColdFusion 会话管理?
How do I use ColdFusion Session Management with a Single Page Application?
我有一个 Angular 4 SPA(单页应用程序),由一台装有 ColdFusion 11 的服务器提供服务。我正在通过 AJAX 调用使用该 ColdFusion 服务器上 .CFC 文件中包含的许多函数。
我希望发生以下情况:
用户转到我的 Angular 4 应用程序页面 (myapp.mydomain.com),然后将被重定向到登录屏幕 (myapp.mydomain.com/login),他们将在其中输入他们的用户名和密码。 Angular 4 应用程序随后将调用服务器上的 .CFC 以验证其登录信息。 .CFC 将 return a "yes" 或 "no" 验证信息。然后 Angular 4 应用程序将它们重定向到 myapp.mydomain.com/home(或者我想让它们去的任何地方)。
同时,我希望 ColdFusion 为该用户创建一个新会话 -- 这样,如果会话超时或用户注销,将拒绝对任何其他 .CFC 的任何进一步调用。
并且如果 ColdFusion 会话超时,我 也 希望 Angular 4 应用注意到这一点并将用户重定向到 /login 路由。
基本上我需要保护客户端(使用 Angular 4 中的 Auth-Guard 式服务,我知道该怎么做)和服务器端(使用 ColdFusion 11 会话管理,我不知道该怎么做),我需要他们不断地就两者的授权状态进行沟通,而不必询问 every single time会话是否仍然有效。 (Angular 4 应用程序能否以某种方式读取 ColdFusion 会话 cookie?)
如何让这两个东西像那样相互配合?还是我对 ColdFusion 会话管理的无知使我看不到一个我还没有想到的更好的解决方案?
如有任何建议,我们将不胜感激。谢谢!
在服务器上,cfc 不能免除自动会话创建和 cookie 管理
对于访问会话变量的请求,必须满足以下条件:
- 客户端必须发出一个被路由到 ColdFusion 的请求(即它命中
cfc
或 cfm
,而不是一些静态 html 或 js)。
- 在所请求的
cfm
/cfc
所在的同一目录或某个祖先目录中必须有一个 Application.cfc
。
Application.cfc
必须使用 this.sessionmanagement = true;
启用会话变量
满足这些条件后,ColdFusion 会将请求与会话相关联。我可以通过 3 种方式建立这种联系:
- 客户端已经有有效的会话 cookie 并在请求中发送它们。您的 CFML 代码可以读取在先前请求中创建的会话变量,并设置新值以供将来请求读取。
- 客户端是新的,没有cookie。 ColdFusion 创建一组新的 cookie 和一个新的会话范围。您的 CFML 代码可以为将来的读取请求设置会话变量。新的 cookie 会连同您的回复自动发送给客户端。
- 客户端发送cookie,但它们对应于一个过期的会话。这与前面的案例一样处理。发送了新的 cookie,并且存在一个空的会话范围供您的 CFML 填充。
在客户端,ajax 请求也不能免除 cookies
底层 XMLHttpRequest 从与所有其他请求相同的 cookie 存储中获取和设置 cookie。如果请求的 URL 与 cookie 的域、路径、安全标志匹配,则 XMLHttpRequest 将发送该 cookie。如果它收到有效的 cookie 作为响应,它将添加它们。
大多数情况下,您只是使用会话变量而不考虑 cookie 或它们是如何到达那里的
因此,对于您的用例,如果您的 login
页面在内部路由到 login.cfm
,并且附近有一个 Application.cfc
,则会话范围可供您尽快使用作为 login.cfm
开始。你可以做到
if(IsDefined("form.username") && IsDefined("form.password")) {
if(...check password [aka the hard part]...) {
session.user = form.username;
location(url="/home");
} else {
location(url="/login");
}
} else {
...print the login form...
}
而您的 logout
代码可以 StructDelete(session, "user")
在其他任何地方,在所有 cfc
和 cfm
中,请求是否来自已登录用户的问题很简单:如果客户端之前已登录,并且会话尚未过期,则 session.user
存在。否则它不会(你会有一个会话 - 总是有一个会话,因为 ColdFusion 在 运行 你的 CFML 代码之前创建了一个 - 但在你把一个放在那里之前不会有 user
变量) .
您也可以在登录请求中设置其他与用户相关的变量(并在注销时取消设置),例如真实姓名、首选项、任何您想要从数据库加载的频繁使用且不经常更新的内容,您可以保留在会话范围内。还有 cflogin
应该有助于管理用户登录,但似乎没有必要。 (参见 Why don't people use <CFLOGIN>?)
你想避免 "having to ask every single time" 的愿望并没有真正实现,但 "asking" 是最小的。客户端在每个 ajax 请求中发送 cookie,这实际上是 "asking" 以继续会话。它必须检查每个 ajax 响应是否有 "session timeout" 错误。在服务器上,每个请求处理函数都必须从检查会话变量是否存在开始。
但是您可以在客户端上使用 ajax 包装器来减轻痛苦。
在服务器上,您可以使用 onRequestStart
为所有请求提供通用的 "precheck",因此您甚至不需要在每个函数的顶部都有 if(...no user...) { return "OH NO"; }
.
我有一个 Angular 4 SPA(单页应用程序),由一台装有 ColdFusion 11 的服务器提供服务。我正在通过 AJAX 调用使用该 ColdFusion 服务器上 .CFC 文件中包含的许多函数。
我希望发生以下情况:
用户转到我的 Angular 4 应用程序页面 (myapp.mydomain.com),然后将被重定向到登录屏幕 (myapp.mydomain.com/login),他们将在其中输入他们的用户名和密码。 Angular 4 应用程序随后将调用服务器上的 .CFC 以验证其登录信息。 .CFC 将 return a "yes" 或 "no" 验证信息。然后 Angular 4 应用程序将它们重定向到 myapp.mydomain.com/home(或者我想让它们去的任何地方)。
同时,我希望 ColdFusion 为该用户创建一个新会话 -- 这样,如果会话超时或用户注销,将拒绝对任何其他 .CFC 的任何进一步调用。
并且如果 ColdFusion 会话超时,我 也 希望 Angular 4 应用注意到这一点并将用户重定向到 /login 路由。
基本上我需要保护客户端(使用 Angular 4 中的 Auth-Guard 式服务,我知道该怎么做)和服务器端(使用 ColdFusion 11 会话管理,我不知道该怎么做),我需要他们不断地就两者的授权状态进行沟通,而不必询问 every single time会话是否仍然有效。 (Angular 4 应用程序能否以某种方式读取 ColdFusion 会话 cookie?)
如何让这两个东西像那样相互配合?还是我对 ColdFusion 会话管理的无知使我看不到一个我还没有想到的更好的解决方案?
如有任何建议,我们将不胜感激。谢谢!
在服务器上,cfc 不能免除自动会话创建和 cookie 管理
对于访问会话变量的请求,必须满足以下条件:
- 客户端必须发出一个被路由到 ColdFusion 的请求(即它命中
cfc
或cfm
,而不是一些静态 html 或 js)。 - 在所请求的
cfm
/cfc
所在的同一目录或某个祖先目录中必须有一个Application.cfc
。 Application.cfc
必须使用this.sessionmanagement = true;
启用会话变量
满足这些条件后,ColdFusion 会将请求与会话相关联。我可以通过 3 种方式建立这种联系:
- 客户端已经有有效的会话 cookie 并在请求中发送它们。您的 CFML 代码可以读取在先前请求中创建的会话变量,并设置新值以供将来请求读取。
- 客户端是新的,没有cookie。 ColdFusion 创建一组新的 cookie 和一个新的会话范围。您的 CFML 代码可以为将来的读取请求设置会话变量。新的 cookie 会连同您的回复自动发送给客户端。
- 客户端发送cookie,但它们对应于一个过期的会话。这与前面的案例一样处理。发送了新的 cookie,并且存在一个空的会话范围供您的 CFML 填充。
在客户端,ajax 请求也不能免除 cookies
底层 XMLHttpRequest 从与所有其他请求相同的 cookie 存储中获取和设置 cookie。如果请求的 URL 与 cookie 的域、路径、安全标志匹配,则 XMLHttpRequest 将发送该 cookie。如果它收到有效的 cookie 作为响应,它将添加它们。
大多数情况下,您只是使用会话变量而不考虑 cookie 或它们是如何到达那里的
因此,对于您的用例,如果您的 login
页面在内部路由到 login.cfm
,并且附近有一个 Application.cfc
,则会话范围可供您尽快使用作为 login.cfm
开始。你可以做到
if(IsDefined("form.username") && IsDefined("form.password")) {
if(...check password [aka the hard part]...) {
session.user = form.username;
location(url="/home");
} else {
location(url="/login");
}
} else {
...print the login form...
}
而您的 logout
代码可以 StructDelete(session, "user")
在其他任何地方,在所有 cfc
和 cfm
中,请求是否来自已登录用户的问题很简单:如果客户端之前已登录,并且会话尚未过期,则 session.user
存在。否则它不会(你会有一个会话 - 总是有一个会话,因为 ColdFusion 在 运行 你的 CFML 代码之前创建了一个 - 但在你把一个放在那里之前不会有 user
变量) .
您也可以在登录请求中设置其他与用户相关的变量(并在注销时取消设置),例如真实姓名、首选项、任何您想要从数据库加载的频繁使用且不经常更新的内容,您可以保留在会话范围内。还有 cflogin
应该有助于管理用户登录,但似乎没有必要。 (参见 Why don't people use <CFLOGIN>?)
你想避免 "having to ask every single time" 的愿望并没有真正实现,但 "asking" 是最小的。客户端在每个 ajax 请求中发送 cookie,这实际上是 "asking" 以继续会话。它必须检查每个 ajax 响应是否有 "session timeout" 错误。在服务器上,每个请求处理函数都必须从检查会话变量是否存在开始。
但是您可以在客户端上使用 ajax 包装器来减轻痛苦。
在服务器上,您可以使用 onRequestStart
为所有请求提供通用的 "precheck",因此您甚至不需要在每个函数的顶部都有 if(...no user...) { return "OH NO"; }
.