Robin Hilliard
我们的常驻 Macromedia MX 专家 Robin Hilliard 向 Builder 澳大利亚的读者展示了如何在 ColdFusion MX 中创建一个会话登录页面。
问题
您好,Robin:
我有一个 Web 站点,该站点在 application.cfm 的开始处创建会话。在出现超时的时候,我得到一个 ColdFusion 错误,而不是我想要的一个登录页面。我想在会话超时的时候将用户重定向到登录页面。
我该怎么做?在一个一些页面需要登录,一些页面不需要登录的站点中很难做到这一点。帮帮忙,谢谢!
回答
在 ColdFusion 中完成这个任务一般来讲其实都相当地简单。假设你有一个目录需要被登录页面保护,那么可以在那个目录的 Application.cfm 添加与以下代码类似的代码。
<!--- Initialise the session scope --->
<cfapplication name="theApp" sessionmanagement="yes">
<!---
Force single-threaded access to session scope - this
can be a particular issue on framed sites, where multiple
requests in the same session arrive at the same time.
--->
<cflock scope="SESSION"
type="exclusive" timeout="1">
<cfparam name="SESSION.authenticated" default=false>
<cfif not SESSION.authenticated>
<!---
We're not logged in yet, either this is the first time we've
requested a page in the protected directory, or a login form
has been submitted.
--->
<cfparam name="FORM.userName"
default="">
<cfparam name="FORM.password" default="">
<cfif FORM.username & FORM.password neq "">
<!---
Something has been entered in the login form. Look up the
username and password, set session.authenticated true if ok.
--->
</cfif>
<cfif not SESSION.authenticated>
<!---
Still not authenticated, render a login form for the user
and cut off the remainder of the request with <cfbreak>.
--->
<cfoutput>
<form action="#CGI.SCRIPT_NAME#" method="POST">
<input name="userName" type="text">
<input name="password" type="password">
<input type="submit">
</form>
</cfoutput>
<cfbreak>
</cfif>
</cfif>
</cflock>
This is fine for a simple authenticated/not authenticated model. Sometimes you
may wish to have multiple levels of access - pleb, manager, uber-manager etc.
To implement this, create a list of roles that are allowed to access this part
of the site. Rename SESSION.authenticated to SESSION.role and default it to
"anonymous".
这对一个简单的身份验证/未验证模型来说相当好。有时候你可能希望具有多层次的访问——一般人员、经理、总经理等。要想实现这一点,你就需要创建一个角色列表,以允许他们访问相应部分的站点。将
SESSION.authenticated重命名为 SESSION.role,然后将其默认值设为“anonymous”。
...
<cfset
requiredRoleList="manager,ubermanager">
<cfparam name="SESSION.role" default="anonymous">
<cfif not listFind(requiredRoleList, SESSION.role)>
...
<cfif FORM.username & FORM.password neq "">
<!---
Something has been entered in the login form. Look up the
username and password, set SESSION.role to matching user role.
--->
</cfif>
<cfif not listFind(requiredRoleList,
SESSION.role)>
...
<cfbreak>
</cfif>
</cfif>
Macromedia 在 ColdFusion MX 中引入了 <cflogin>、<cfloginuser>、 getAuthUser() 和 isUserInRole() 标记/函数来完成这些事情,同时还添加了一个特性,根据角色来限制对 ColdFusion 组件(CFC)业务逻辑方法的访问。这样做是件好事,因为用户界面可以独立于组件代码修改,而无须担心不小心暴露以前由 UI 保护的功能——即使完成移除 HTML 用户界面并使用 Flash 或者一个访问 CFC的 Web 服务客户来替代 HTML 用户界面。要查看有关使用 <cflogin> 的信息,请参阅在线文档。
确保你也阅读了 Christian Cantrell's blog 上的这个条目:
不管你做什么,这段代码都很通用,你可能会需要在自己的站点中重用它。重用这段代码的最简单的方法是将其包装为一个自定义标记,这个自定义标记以 requiredRoleList 作为一个属性并为你完成所有的处理过程。将标记放在 webroot 之外的一个 cfmapping 中(如果你已经以一个 EAR/WAR 进行了部署,那么应该在 WEB-INF 之下)以保证身体验证代码最大限度的安全。
不幸的是,我不知道你得到的实际错误消息是什么,也不知道你在创建会话时真正想做什么。可能你的代码假设一个会话的作用域变量在删除之后依然存在——你可以在使用会话变量之前使用 <cfparam> 从而保证他们的确存在。不管怎样,我希望这个例子能够给你一些帮助。