在两个站点之间共享数据(如果请求有效)

时间:2014-10-16 17:03:24

标签: coldfusion railo

我正在网站上工作,它有一个文档页面,只有来自其他网站的成员才能访问,而这个其他网站有一个页面,只有来自我正在处理的网站的成员才能访问该页面

目前通过查看http推荐人来完成此操作,因此其他网站有一个链接,可以说www.mysite.com/for-their-members-page/,如果http推荐人是www.theirsite.com / members /我们知道来自他们网站的有效请求,他们必须在他们的成员区域内签署,而另一方面也是如此。

我首先关注的是http推荐人很容易被伪造,但另一个问题取决于用户浏览器或安全设置,你可能甚至没有得到那个http推荐人。

是否有任何解决方案,以便我可以验证请求是否有效 - 即它是来自其他网站成员区域?反之亦然,他们可以验证对其网页的请求是否实际来自我们网站的成员?

感谢您提供任何帮助或指示:)

3 个答案:

答案 0 :(得分:1)

一个“安全”的解决方案是使用ColdFusion会话变量。

在站点A上,您需要一个Session变量,用于标识用户已登录(例如,您有Session.UserName)。然后,您有一个简单的身份验证检查页面(check.cfm)执行此操作:

<cfif IsDefined("Session.Username")>1<cfelse>0</cfif>

站点A链接到站点B,如下所示:

http://siteB.com/page.cfm?remoteID=<cfoutput>#Session.CFID#&remoteToken=#Session.CFToken#</cfoutput>

现在,站点B可以通过执行以下操作来检查用户是否登录到站点A:

<cfhttp url="http://siteA.com/check.cfm?CFID=#URL.remoteID#&CFToken=#URL.remoteToken#"/>

答案 1 :(得分:0)

对于你的第一个问题,答案是肯定是的。 cgi变量很容易伪造,不应该用于任何类型的“真实”身份验证。

其次,没有一种“简单”的方案,每个人都用来做你想要做的事情,但有许多“单点登录”解决方案使用针对第三个来源的身份验证。例如,您是否曾经去过一个允许您使用Google或Facebook帐户登录的视频?他们正在使用oAuth--一种由大型社交媒体服务支持的SSO标准。

对于你正在做的事情来说,这可能有点过头了,但是当我不知道整体风险是什么时,真的很难“推荐”一些东西。

例如,您可以在服务器A上创建一个锁定到服务器B的IP地址的页面(反之亦然)。页面可以返回UUID - 您创建并存储在应用程序范围内的内容,并每天或每小时或5分钟轮换(适用于风险的任何内容)。然后,您可以存储OTHER服务器UUID并使用cfhttp定期刷新它:

<cfhttp url="otherserver/myUUID.cfm"/>
<cfset application.otherserveruuid = trim(cfhttp.filecontent)/>

现在每个服务器都知道两件事 - 它是OWN UUID和OTHER SERVER的UUID。

最后,将UUID附加到OTHER服务器的链接,并添加一个检查(在传入服务器上)以确保它存在并匹配来自服务器的UUID。

这个方案可行但是:

  • 这不是非常安全 - 只是更难伪造。例如,如果您每天只更改一次UUID,那么有人可能只是在白天将链接传递给任何人。
  • 这不是精细的。从你的问题我把它当作你想要的。您不希望对特定用户进行身份验证。您并不关心他们是谁 - 您只关心来自其他网站

只要您了解并且可以使用这2个cavaets,这将有效。正如您可能想象的那样,有很多其他方法可以做到这一点。你可能会想到一些:)

答案 2 :(得分:0)

我会把这个留在这里,无论是谁可以从中提取一些东西,但this is the more elegant answer.,并禁用链接共享而不进行登录共享。


<cfif len(trim(Arguments.username)) is "">
  <cfset results.state = 0>
  <cfset results.message = "Username argument is not defined">
  <cfreturn results>
</cfif>

<cfif len(trim(Arguments.password)) is "">
  <cfset results.state = 0>
  <cfset results.message = "Password argument is not defined">
  <cfreturn results>
</cfif>

<cfif not isDefined("Arguments.CustID")>
  <cfset results.state = 0>
  <cfset results.message = "Customer ID (representing the user of your site) is required.">
  <cfreturn results>
</cfif>

<cfquery name="ValidateSite"...>
  select SiteID from othersites
   where username = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.username#">
   where password = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.password#">
     and Active = 1
</cfquery>

<cfif ValidateSite.recordcount eq 1>
  <cfset results.Passkey = Hash(Arguments.username & "_" & Arguments.custID)>
  <!--- I chose hash because it will reliably create the same key when the referring site provides the same data. Wheras, a lot of other functions might not. --->
  <cfquery name="CheckID"...>
    Select SiteID
      from PermKeys
     where SiteID=<cfparam cfsqltype="cf_sql_integer" value="#ValidateSite.siteID#">
       and PassKey=<cfparam cfsqltype="cf_sql_varchar" value="#results.PassKey#">
       and custID=<cfparam cfsqltype="cf_sql_varchar" value="#Arguments.custID#">)
  </cfquery>
  <cfif CheckID.recordcount eq 0>
    <cfquery...>
      insert into PermKeys(SiteID,Passkey,CustID)
      values(<cfparam cfsqltype="cf_sql_integer" value="#ValidateSite.siteID#">,<cfparam cfsqltype="cf_sql_varchar" value="#results.PassKey#">,<cfparam cfsqltype="cf_sql_varchar" value="#Arguments.custID#">)
    </cfquery>
    <cfset results.message = "Authentication for this customer created.">
  <cfelse>
    <cfset results.message = "Authentication for this customer previously created. Authentication Key will always be the same. Please store the authentication keys, passed back as passKey, on your own server so that a call isn't needed each time.">
  </cfif>
  <cfset results.state = 1>
  <cfset results.siteID = ValidateSite.siteID>
  <cfset results.custID = Arguments.custID>
<cfelse>
  <cfset results.state = 0>
  <cfset results.message = "User not found.">
</cfif>
<cfreturn results>

如果成功,这将返回

  • 1州。
  • SiteID,数字ID
  • PassKey,每个custID唯一
  • CustID(由Arguments.custID传递)。在这个例子中实际上并不需要。
  • 一条消息。

如果站点凭据验证失败或提供不正确,则返回

  • 状态0。
  • 解释原因的消息。

然后我调用webservice,获取用户的凭据并返回类似

的链接

http://docssite.com/authorize/index.cfm?site=#siteID#&passkey=#passkey#&customerID=#custID#

authorize的index.cfm将检查这三个针对PermKeys的url参数,确保它是合法的,并将用户IN记录下来。您甚至可以直接在网址中传递docID,并将该决定用作是否显示docID。

如果您还在列表中传递了一个docID,您可以轻松地将所有参数与cfhttp连接到相同的URL并返回文档。

然后,您可以编写类似的Web服务来删除过期的凭据(比如从客户站点取消订阅的人,您不希望他们的凭据仍然有效)。

客户站点可以(并且应该)跟踪他们已经调用过Web服务的用户,并在他们自己的数据库中保存他们的密码和CustID(每个客户都是唯一的),这样他们就不需要重复了调用您的Web服务获取相同的信息。