如何保护Webservice CFC以与AJAX一起使用 [英] How to secure a webservice CFC for use with AJAX

查看:331
本文介绍了如何保护Webservice CFC以与AJAX一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个启用远程访问的CFC文件,我使用它来执行各种管理任务,如从数据库添加/删除图像记录。对此CFC的调用是通过AJAX通过我的管理页面上的自定义JavaScript。我把CFC放在我认为是一个安全的目录,但是有一些问题,图像消失了自己,我已经发现它是不安全的。



我想确保CFC。已经有一个基于会话的安全CFC,我用于管理页面,并且每当请求一个管理页面时调用它的保护方法,如果认证失败,这将重定向用户。我可以在我的CFC上使用这个东西吗?如果是这样,什么是最好的方式来实现呢?



以下是我的例子CFC:

 < cfcomponent 
name =test
displayname =test
output =false
hint =test
> ;

<!--- pseudo constructor --->
< cfscript>
variables.propertyImageDAO = CreateObject(component,cfcs.dataobjects.property_imageDAO)。init(APPLICATION.dsn);
variables.propertyImageGateway = CreateObject(component,cfcs.dataobjects.property_imageGateway)。init(APPLICATION.dsn);
< / cfscript>

<!--- constructor --->
< cffunction name =initaccess =publicoutput =falsereturntype =any
hint =Constructor for this CFC>

<!--- return this CFC --->
< cfreturn this />
< / cffunction>

<!--- CRUD方法(创建,读取,更新,删除)--->
<!--- CREATE:在数据库中插入一个新的property_image --->
< cffunction name =createRecordaccess =remoteoutput =true
hint =创建一个新的property_image记录并返回一个包含指示成功的boolean $ b操作失败,id(id)和包含消息
>的字符串(消息)

< cfargument name =nametype =anyrequired =falsedefault =/>
< cfargument name =alttype =anyrequired =true/>

<!--- initialize variables --->
< cfset var results = StructNew()/>

<!--- create property bean --->
< cfscript>
var propertyImageBean = CreateObject(component,cfcs.beans.property_image)。init(
'',
arguments.name,
arguments.alt
);
results = propertyImageDAO.createRecord(propertyImageBean);
< / cfscript>

<!--- return the struct --->
< cfoutput> #SerializeJSON(results)#< / cfoutput>
< / cffunction>
<!--- READ:从数据库中读取一个property_image并填充property_image对象--->
< cffunction name =readRecordaccess =remoteoutput =truereturntype =void
hint =从数据库读取property_image数据并返回JSON

<!--- take property_image bean as argument --->
< cfargument name =idtype =numericrequired =true/>

<!--- initialize variables --->
< cfset var results = StructNew()/>

<!--- create property bean --->
< cfscript>
propertyImageBean = CreateObject(component,cfcs.beans.property_image);
propertyImageBean.setid(arguments.id);
propertyImageDAO.readRecord(propertyImageBean);
< / cfscript>

<!--- return the struct --->
< cfoutput> #SerializeJSON(propertyImageBean)#< / cfoutput>
< / cffunction>
<!--- DELETE:从数据库中读取一个property_image并填充property_image对象--->
< cffunction name =deleteRecordaccess =remoteoutput =truereturntype =void
hint =从数据库读取property_image数据并返回JSON

<!--- take property_image bean as argument --->
< cfargument name =idtype =numericrequired =true/>

<!--- initialize variables --->
< cfset var results = StructNew()/>

<!--- create property bean --->
< cfscript>
results = propertyImageDAO.deleteRecordById(arguments.id);
< / cfscript>

<!--- return the struct --->
< cfoutput> #SerializeJSON(results)#< / cfoutput>
< / cffunction>
<!--- DELETERECORDS:从数据库中删除一个property_image --->
< cffunction name =deleteRecordsaccess =remoteoutput =truereturntype =void
hint =从数据库中删除property_image数据并返回JSON

<!--- take property_image bean as argument --->
< cfargument name =imageIdListtype =stringrequired =true/>

<!--- initialize variables --->
< cfset var results = StructNew()/>

<!--- delete DB records --->
< cfscript>
results = propertyImageDAO.deleteRecordsByIdList(arguments.imageIdList);
< / cfscript>
<!--- delete files --->

<!--- return the struct --->
< cfoutput> #SerializeJSON(results)#< / cfoutput>
< / cffunction>
<!--- DELETERECORDS:从数据库中读取一个property_image并填充property_image对象--->
< cffunction name =deleteRecordByIdaccess =remoteoutput =truereturntype =void
hint =从数据库中删除property_image数据并返回一个JSON

<!--- take property_image bean as argument --->
< cfargument name =idtype =numericrequired =true/>

<!--- initialize variables --->
< cfset var results = StructNew()/>

<!--- delete DB records --->
< cfscript>
results = propertyImageDAO.deleteRecordById(arguments.id);
< / cfscript>
<!--- delete files --->

<!--- return the struct --->
< cfoutput> #SerializeJSON(results)#< / cfoutput>
< / cffunction>
<!--- DELETERECORDSBYIDLIST:从数据库中读取一个property_image并填充property_image对象--->
< cffunction name =deleteRecordsByIdListaccess =remoteoutput =truereturntype =void
hint =从数据库中删除property_image数据并返回JSON

<!--- take property_image bean as argument --->
< cfargument name =imageIdListtype =stringrequired =true/>

<!--- initialize variables --->
< cfset var results = StructNew()/>

<!--- delete DB records --->
< cfscript>
results = propertyImageDAO.deleteRecordsByIdList(arguments.imageIdList);
< / cfscript>

<!--- return the struct --->
< cfoutput> #SerializeJSON(results)#< / cfoutput>
< / cffunction>

< cffunction name =deleteImagesByNameListaccess =remoteoutput =truereturntype =void
hint =从数据库中删除property_image数据并返回JSON ;

<!--- take property_image bean as argument --->
< cfargument name =imageNameListtype =stringrequired =true/>

<!--- initialize variables --->
< cfset var results = StructNew()/>

<!--- delete DB records --->
< cfscript>
results = propertyImageDAO.deleteImagesByNameList(arguments.imageNameList);
< / cfscript>

<!--- return the struct --->
< cfoutput> #SerializeJSON(results)#< / cfoutput>
< / cffunction>

<!--- READ:从数据库读取property_image并填充property_image对象--->
< cffunction name =getByIdListaccess =remoteoutput =truereturntype =void
hint =从数据库读取property_image数据并返回JSON

<!--- take property_image bean as arguments --->
< cfargument name =imageIdListtype =stringrequired =true/>

<!--- initialize variables --->
< cfset var results = StructNew()/>

<!--- create property bean --->
< cfscript>
qGetByIdList = propertyImageGateway.getByIdList(arguments.imageIdList);
< / cfscript>

<!--- convert into JSON friendly format --->
< cfif qGetByIdList.recordCount GT 0>
< cfset images = ArrayNew(1)>
< cfloop query =qGetByIdListstartRow =1endRow =#qGetByIdList.recordCount#>
< cfscript>
//创建图像结构并赋值
image = StructNew();
image.id = id;
image.name = name;
image.alt = alt;
//追加到JSON响应
ArrayAppend(images,image);
< / cfscript>
< / cfloop>
< cfset results.images = images>
< / cfif>
< cfoutput> #SerializeJSON(results)#< / cfoutput>
< / cffunction>
<!--- READ:从数据库中读取一个property_image并填充property_image对象--->
< cffunction name =updateRecordaccess =remoteoutput =truereturntype =void
hint =从数据库读取property_image数据并返回JSON

<!--- take property_image bean as argument --->
< cfargument name =idtype =numericrequired =true/>
< cfargument name =nametype =anyrequired =true/>
< cfargument name =alttype =anyrequired =true/>

<!--- initialize variables --->
< cfset var results = StructNew()/>

<!--- create property bean --->
< cfscript>
propertyImageBean = CreateObject(component,cfcs.beans.property_image)。init(
arguments.id,
arguments.name,
arguments.alt
);
results = propertyImageDAO.updateRecord(propertyImageBean);
< / cfscript>

<!--- return the struct --->
< cfoutput> #SerializeJSON(results)#< / cfoutput>
< / cffunction>

解决方案>

要强制执行您的认证逻辑,应该使用此逻辑在Application.cfc中包装所有远程CFC调用。



不幸的是,您使用的是CF8,因此您不能使用Application.cfc的 onCFCRequest 方法包装所有的远程请求。但是你可以通过检查目标页是否以'cfc'结尾在 onRequestStart p>

 < cffunction name =onRequestStart> 
< cfargment name =targetPage>
< cfif right(targetPage,4)eq'.cfc'>
<!--- Perform authentication check --->
< cfif not loggedIn>
<!---返回未授权给客户端--->
< cfheader statuscode =401>
< cfabort>
< / cfif>
< / cfif>
< / cffunction>然后,在你的Ajax fail 处理程序中,将



<检查401状态代码并向用户显示指示需要登录的消息。


I have a CFC file with remote access enabled, I am using this to perform various admin tasks such as adding / removing image records from a database. The calls to this CFC are made through AJAX via custom JavaScript on my admin pages. I placed the CFC in what I thought was a secured directory but having had some issues with images disappearing of their own accord and I have since found it is not secure at all.

I would like to secure the CFC. There is already a session based security CFC that I use for the admin pages, and the protect method of that gets called each time one of the admin pages is requested, this redirects a user if the authentication fails. Can I use something this on my CFC? IF so, what is the best way to implement it? If not, how should I implement security on it?

Below is my example CFC:

<cfcomponent
  name="test"
  displayname="test"
  output="false"
  hint="test"
>

<!--- pseudo constructor --->
<cfscript>
    variables.propertyImageDAO = CreateObject("component","cfcs.dataobjects.property_imageDAO").init(APPLICATION.dsn);
    variables.propertyImageGateway = CreateObject("component","cfcs.dataobjects.property_imageGateway").init(APPLICATION.dsn);
</cfscript>

<!--- constructor --->
<cffunction name="init" access="public" output="false" returntype="any"
        hint="Constructor for this CFC">

    <!--- return this CFC --->
    <cfreturn this />
</cffunction>

<!--- CRUD methods (create, read, update, delete) --->
<!--- CREATE: inserts a new property_image into the database --->
<cffunction name="createRecord" access="remote" output="true" 
        hint="Creates a new property_image record and returns a struct containing a boolean (success) indicating the success or
        failure of the operation, an id (id), and a string (message) containing a message"
        >

    <cfargument name="name" type="any" required="false" default="" />
    <cfargument name="alt" type="any" required="true" />

    <!--- initialize variables --->
    <cfset var results = StructNew() />

    <!--- create property bean --->
    <cfscript>
        var propertyImageBean = CreateObject("component","cfcs.beans.property_image").init(
            '',
            arguments.name,
            arguments.alt
        );
        results = propertyImageDAO.createRecord(propertyImageBean);
    </cfscript>

    <!--- return the struct --->
    <cfoutput>#SerializeJSON(results)#</cfoutput>
</cffunction>
<!--- READ: reads a property_image from the database and populates the property_image object --->
<cffunction name="readRecord" access="remote" output="true" returntype="void"
   hint="Reads property_image data from the database and returns a JSON">

    <!--- take property_image bean as argument --->
    <cfargument name="id" type="numeric" required="true" />

    <!--- initialize variables --->
    <cfset var results = StructNew() />

    <!--- create property bean --->
    <cfscript>
        propertyImageBean = CreateObject("component","cfcs.beans.property_image");
        propertyImageBean.setid(arguments.id);
        propertyImageDAO.readRecord(propertyImageBean);
    </cfscript>

    <!--- return the struct --->
    <cfoutput>#SerializeJSON(propertyImageBean)#</cfoutput>
</cffunction>
<!--- DELETE: reads a property_image from the database and populates the property_image object --->
<cffunction name="deleteRecord" access="remote" output="true" returntype="void"
   hint="Reads property_image data from the database and returns a JSON">

    <!--- take property_image bean as argument --->
    <cfargument name="id" type="numeric" required="true" />

    <!--- initialize variables --->
    <cfset var results = StructNew() />

    <!--- create property bean --->
    <cfscript>
        results = propertyImageDAO.deleteRecordById(arguments.id);
    </cfscript>

    <!--- return the struct --->
    <cfoutput>#SerializeJSON(results)#</cfoutput>
</cffunction>   
<!--- DELETERECORDS: deletes a property_image from the database --->
<cffunction name="deleteRecords" access="remote" output="true" returntype="void"
   hint="Deletes property_image data from the database and returns a JSON">

    <!--- take property_image bean as argument --->
    <cfargument name="imageIdList" type="string" required="true" />

    <!--- initialize variables --->
    <cfset var results = StructNew() />

    <!--- delete DB records --->
    <cfscript>
        results = propertyImageDAO.deleteRecordsByIdList(arguments.imageIdList);
    </cfscript>
    <!--- delete files --->

    <!--- return the struct --->
    <cfoutput>#SerializeJSON(results)#</cfoutput>
</cffunction>   
<!--- DELETERECORDS: reads a property_image from the database and populates the property_image object --->
<cffunction name="deleteRecordById" access="remote" output="true" returntype="void"
   hint="Deletes property_image data from the database and returns a JSON">

    <!--- take property_image bean as argument --->
    <cfargument name="id" type="numeric" required="true" />

    <!--- initialize variables --->
    <cfset var results = StructNew() />

    <!--- delete DB records --->
    <cfscript>
        results = propertyImageDAO.deleteRecordById(arguments.id);
    </cfscript>
    <!--- delete files --->

    <!--- return the struct --->
    <cfoutput>#SerializeJSON(results)#</cfoutput>
</cffunction> 
<!--- DELETERECORDSBYIDLIST: reads a property_image from the database and populates the property_image object --->
<cffunction name="deleteRecordsByIdList" access="remote" output="true" returntype="void"
   hint="Deletes property_image data from the database and returns a JSON">

    <!--- take property_image bean as argument --->
    <cfargument name="imageIdList" type="string" required="true" />

    <!--- initialize variables --->
    <cfset var results = StructNew() />

    <!--- delete DB records --->
    <cfscript>
        results = propertyImageDAO.deleteRecordsByIdList(arguments.imageIdList);
    </cfscript>

    <!--- return the struct --->
    <cfoutput>#SerializeJSON(results)#</cfoutput>
</cffunction>   

<cffunction name="deleteImagesByNameList" access="remote" output="true" returntype="void"
   hint="Deletes property_image data from the database and returns a JSON">

    <!--- take property_image bean as argument --->
    <cfargument name="imageNameList" type="string" required="true" />

    <!--- initialize variables --->
    <cfset var results = StructNew() />

    <!--- delete DB records --->
    <cfscript>
        results = propertyImageDAO.deleteImagesByNameList(arguments.imageNameList);
    </cfscript>

    <!--- return the struct --->
    <cfoutput>#SerializeJSON(results)#</cfoutput>
</cffunction>   

<!--- READ: reads a property_image from the database and populates the property_image object --->
<cffunction name="getByIdList" access="remote" output="true" returntype="void"
   hint="Reads property_image data from the database and returns a JSON">

    <!--- take property_image bean as argument --->
    <cfargument name="imageIdList" type="string" required="true" />

    <!--- initialize variables --->
    <cfset var results = StructNew() />

    <!--- create property bean --->
    <cfscript>
        qGetByIdList = propertyImageGateway.getByIdList(arguments.imageIdList);
    </cfscript>

    <!--- convert into JSON friendly format --->
    <cfif qGetByIdList.recordCount GT 0>
      <cfset images = ArrayNew(1)>
      <cfloop query="qGetByIdList" startRow="1" endRow="#qGetByIdList.recordCount#">
          <cfscript>
              // create image struct and assign values
              image = StructNew();
              image.id = id;
              image.name = name;
              image.alt = alt;
              // append to JSON response
              ArrayAppend(images,image);
          </cfscript>
      </cfloop>
      <cfset results.images = images>
    </cfif>
    <cfoutput>#SerializeJSON(results)#</cfoutput>
</cffunction>
<!--- READ: reads a property_image from the database and populates the property_image object --->
<cffunction name="updateRecord" access="remote" output="true" returntype="void"
   hint="Reads property_image data from the database and returns a JSON">

    <!--- take property_image bean as argument --->
    <cfargument name="id" type="numeric" required="true" />
    <cfargument name="name" type="any" required="true" />
    <cfargument name="alt" type="any" required="true" />

    <!--- initialize variables --->
    <cfset var results = StructNew() />

    <!--- create property bean --->
    <cfscript>
        propertyImageBean = CreateObject("component","cfcs.beans.property_image").init(
            arguments.id,
            arguments.name,
            arguments.alt
        );
        results = propertyImageDAO.updateRecord(propertyImageBean);
    </cfscript>

    <!--- return the struct --->
    <cfoutput>#SerializeJSON(results)#</cfoutput>
</cffunction>

解决方案

To enforce your authentication logic, you should wrap all remote CFC calls in Application.cfc with this logic.

Unfortunately you're using CF8, so you can't use the onCFCRequest method of Application.cfc to easily wrap all your remote requests. But you can do the same thing in onRequestStart by checking if the target page ends in '.cfc'.

<cffunction name="onRequestStart">
    <cfargment name="targetPage">
    <cfif right(targetPage, 4) eq '.cfc'>
        <!--- Perform authentication check --->
        <cfif not loggedIn>
            <!--- Return "unauthorized" to the client --->
            <cfheader statuscode="401"> 
            <cfabort>
        </cfif>
    </cfif>
</cffunction>

Then, in your Ajax fail handler, check for a 401 status code and display a message to the user indicating the need for logging in.

这篇关于如何保护Webservice CFC以与AJAX一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆