更新会话变量是否将用户踢到登录页面?

Updating session variables kick user to login page or not?

我正在开发新的应用程序并使用会话变量来存储一些用户信息,如电子邮件、权限级别等。我想知道一旦用户决定更新让他们自己说电子邮件或权限不会马上影响。会话变量只有在注销然后再次登录时才会更新。我知道避免这种情况的一种方法是更新现有的会话变量。这是我在用户登录时在会话变量中设置的代码示例:

<cfset local.appStruct = structNew()>
<cfset structInsert(local.appStruct, "SysAdmin", checkUser.SystemAdmin, true)>
<cfset structInsert(local.appStruct, "UserName", checkUser.UserName, true)>
<cfset structInsert(local.appStruct, "AccountID", checkUser.AccountID, true)>
<cfset structInsert(local.appStruct, "Email", checkUser.Email, true)>
<cfset structInsert(local.appStruct, "TempPW", checkUser.TempPassword, true)>
<cfset structInsert(local.appStruct, "AccessType", permissionType, true)>
<cfset structInsert(local.appStruct, "AccessLevel", permissionLevel, true)>
<cfset structInsert(local.appStruct, "AccessList", permissionList, true)>
<cfset SESSION.AccountInfo = appStruct> 

上面我只是展示了保存在会话范围内的字段。所有值都是从我没有显示的查询中提取的。例如 TempPW 正在存储临时密码,我不需要更新它,因为一旦用户设置了新密码,就会自动移至登录页面。在他们更新 emailaccess type 的其他情况下,我不确定我是否应该注销用户或尝试更新会话范围?以一种或另一种方式进行操作是否存在安全风险?我只是想在我的应用程序中实施最佳实践。谢谢你。

从用户的角度来看,必须注销并重新登录听起来不太理想。

我建议在用户更新他们的电子邮件或其他值时更新会话范围。 与要求用户注销并重新登录相比,安全性应该没有区别。

在用户更新他们的电子邮件的页面上,更新数据库中的值后只需覆盖会话变量,例如:

<cfset SESSION.AccountInfo.Email = form.email>
<cfset SESSION.AccessLevel = "SOME_NEW_ACCESS_LEVEL">
etc...

作为附带建议,我会停止使用 structInsert,您可以简单地设置变量并避免调用函数的(非常小的)性能开销。您上面的相同代码可以重写为:

<cfset local.appStruct = structNew()>
<cfset local.appStruct.SysAdmin = checkUser.SystemAdmin>
<cfset local.appStruct.UserName = checkUser.UserName>
<cfset local.appStruct.AccountID = checkUser.AccountID>
<cfset local.appStruct.Email = checkUser.Email>
<cfset local.appStruct.TempPW = checkUser.TempPassword>
<cfset local.appStruct.AccessType = permissionType>
<cfset local.appStruct.AccessLevel = permissionLevel>
<cfset local.appStruct.AccessList = permissionList>
<cfset SESSION.AccountInfo = appStruct> 

如果出于某种原因,您需要保留结构键的大小写,您可以使用数组样式语法,例如:

<cfset local.appStruct = structNew()>
<cfset local.appStruct["SysAdmin"] = checkUser.SystemAdmin>
<cfset local.appStruct["UserName"] = checkUser.UserName>
<cfset local.appStruct["AccountID"] = checkUser.AccountID>
<cfset local.appStruct["Email"] = checkUser.Email>
<cfset local.appStruct["TempPW"] = checkUser.TempPassword>
<cfset local.appStruct["AccessType"] = permissionType>
<cfset local.appStruct["AccessLevel"] = permissionLevel>
<cfset local.appStruct["AccessList"] = permissionList>
<cfset SESSION.AccountInfo = appStruct> 

您可以使用 <cfdump 来查看两个结构之间的差异,以及键如何在第一个示例中全部为小写,或者在第二个示例中保留了它们的 upper/lower 大小写。

<cfdump var="#local.appStruct#" />

对不起,我可能跑题了,希望对您有所帮助。

这不是一个答案,而是一个关于如何简化 Struct 创建的评论。

正如我在对@sqrl0 的回答的评论中提到的,您可以使用标签:

<cfset local.appStruct = {
    "SysAdmin"    : checkUser.SystemAdmin ,
    "UserName"    : checkUser.UserName ,
    "AccountID"   : checkUser.AccountID ,
    "Email"       : checkUser.Email ,
    "TempPW"      : checkUser.TempPassword ,
    "AccessType"  : permissionType ,
    "AccessLevel" : permissionLevel ,
    "AccessList"  : permissionList
}>
<cfset SESSION.AccountInfo = local.appStruct> 

或 CFScript:注意:您不需要将结构复制到 SESSION.AccountInfo。你可以在那里创建它。

<cfscript>
  SESSION.AccountInfo = {
    "SysAdmin"    : checkUser.SystemAdmin ,
    "UserName"    : checkUser.UserName ,
    "AccountID"   : checkUser.AccountID ,
    "Email"       : checkUser.Email ,  
    "TempPW"      : checkUser.TempPassword ,
    "AccessType"  : permissionType ,
    "AccessLevel" : permissionLevel ,
    "AccessList"  : permissionList
  }
</cfscript>

确保任何被覆盖的变量都是这样的。这是不对不同事物使用相同变量名的主要原因之一。当您尝试调试时,意外覆盖会让您彻底崩溃。