B/S应用中的ActiveX数字签名相关问题杂谈

       我们在开发B/S项目时,往往会面临需要封装一些逻辑在客户端运行或者是需要提取一些客户端环境信息等方面的情况,基于微软技术我们一般会选择使用AcitveX技术,通过javascript调用ActiveX提供的对象来满足业务上的需求。不过,随着Windows XP SP2的到来,让问题变得更加复杂且难以处理。

       首先,IE 7 默认是阻止非法签名的ActiveX控件安装。虽然可以通过降低IE安全级别来克服这一问题,但我们无法要求让所有的客户端都通过此方法来解决这一问题,特别是Internet用户。降低安全级别安装后的结果如下图:

image

       其次,ActiveX控件的分发形式。常用的是CAB和独立安装包(EXE)。CAB文件包含.INF文件或软件分发.OSD文件,也可以包含其他软件组件,如 ActiveX 控件(.OCX)、.DLL文件、.EXE文件、Java类文件或小程序。当Web页上OBJECT元素的CODEBASE特性引用包含.INF文件的.CAB文件时,Internet Explorer将自动把.CAB文件作为软件分发单位下载并安装,每次访问时还会自动检测版本并进行更新。而INF文件则是一个文本文件,指定运行控件所需要下载或者呈交的文件(比如.DLL或者其它.OCX);EXE文件这儿就不多介绍了。值得我们注意的是,当我们开发的ActiveX控件无法正常在客户机安装时,前者带的问题会更大一些。例如,我们发布了一个基于Internet的B/S系统,用户通过IE访问系统时需要下载安装一个Active控件包(.CAB),当此控件包因为安全原因无法安装时,会带来网络流量问题。因为用户每次访问页面都需要下载这个包,当这个包比较大的时候,这个问题就更为突出。而EXE包只需要下载并安装一次。当然,这个是因为IE了非法签名ActiveX控件安装引起的,那么下面我们就谈谈如何让ActiveX控件在客户机中顺利安装。

       要让ActiveX控件在客户机中顺利安装,需要对我们的CAB进行数字签名,这方面就不多说了,网上有很多这方面的资料,为了让用户可以信任我们的CAB包,我们需要经过授权的证书,在具体的项目中,我们选用了VeriSign Class3(相关信息)。当我们对CAB包签名之后发现客户端安装仍然有问题,虽然可以识别到我们的CAB包是有效的签名,但仍然提示是未经验证的,很多Windows XP SP2环境中仍然无法安装。究其原因,是因为我们的ActiveX控件没有实现ISafeObject接口,所以Windows XP SP2对我们的控件提出了警告。接下来的工作就比较简单了,加上对ISafeObject接口的实现就好了,然后对生成好的CAB包再进行签名。

       以VB开发的ActiveX为例,实现ISafeObject接口的范例程序如下:

ContractedBlock.gif ExpandedBlockStart.gif Code
' 模块中的定义部分
Option Explicit

Public Const IID_IDispatch = "{00020400-0000-0000-C000-000000000046}"
Public Const IID_IPersistStorage = _
    
"{0000010A-0000-0000-C000-000000000046}"
Public Const IID_IPersistStream = _
    
"{00000109-0000-0000-C000-000000000046}"
Public Const IID_IPersistPropertyBag = _
    
"{37D84F60-42CB-11CE-8135-00AA004BB851}"

Public Const INTERFACESAFE_FOR_UNTRUSTED_CALLER = &H1
Public Const INTERFACESAFE_FOR_UNTRUSTED_DATA = &H2
Public Const E_NOINTERFACE = &H80004002
Public Const E_FAIL = &H80004005
Public Const MAX_GUIDLEN = 40

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
      (pDest 
As Any, pSource As Any, ByVal ByteLen As Long)
Public Declare Function StringFromGUID2 Lib "ole32.dll" (rguid As _
      Any, ByVal lpstrClsId 
As Long, ByVal cbMax As IntegerAs Long

Public Type udtGUID
    Data1   
As Long
    Data2   
As Integer
    Data3   
As Integer
    Data4(
7)   As Byte
End Type

Public m_fSafeForScripting     As Boolean
Public m_fSafeForInitializing     As Boolean

Sub Main()
    m_fSafeForScripting 
= True
    m_fSafeForInitializing 
= True
End Sub

' -----------------------分隔线-------------------------

' 类文件中的代码
Private Sub Class_Initialize()
    m_fSafeForScripting 
= True
    m_fSafeForInitializing 
= True
End Sub

Private Sub IObjectSafety_GetInterfaceSafetyOptions(ByVal riid As _
        
Long, pdwSupportedOptions As Long, pdwEnabledOptions As Long)
    
Dim Rc               As Long
    
Dim rClsId       As udtGUID
    
Dim IID             As String
    
Dim bIID()       As Byte

    pdwSupportedOptions 
= INTERFACESAFE_FOR_UNTRUSTED_CALLER Or _
                                                INTERFACESAFE_FOR_UNTRUSTED_DATA

    
If (riid <> 0Then
        CopyMemory rClsId, ByVal riid, 
Len(rClsId)

        bIID 
= String$(MAX_GUIDLEN, 0)
        Rc 
= StringFromGUID2(rClsId, VarPtr(bIID(0)), MAX_GUIDLEN)
        Rc 
= InStr(1, bIID, vbNullChar) - 1
        IID 
= Left$(UCase(bIID), Rc)

        
Select Case IID
            
Case IID_IDispatch
                pdwEnabledOptions 
= IIf(m_fSafeForScripting, _
                    INTERFACESAFE_FOR_UNTRUSTED_CALLER, 
0)
                
Exit Sub
            
Case IID_IPersistStorage, IID_IPersistStream, _
                  IID_IPersistPropertyBag
                pdwEnabledOptions 
= IIf(m_fSafeForInitializing, _
                    INTERFACESAFE_FOR_UNTRUSTED_DATA, 
0)
                
Exit Sub
            
Case Else
                Err.Raise E_NOINTERFACE
                
Exit Sub
        
End Select
    
End If
End Sub

Private Sub IObjectSafety_SetInterfaceSafetyOptions(ByVal riid As _
        
Long, ByVal dwOptionsSetMask As Long, ByVal dwEnabledOptions As Long)
    
Dim Rc                       As Long
    
Dim rClsId               As udtGUID
    
Dim IID                     As String
    
Dim bIID()               As Byte

    
If (riid <> 0Then
        CopyMemory rClsId, ByVal riid, 
Len(rClsId)

        bIID 
= String$(MAX_GUIDLEN, 0)
        Rc 
= StringFromGUID2(rClsId, VarPtr(bIID(0)), MAX_GUIDLEN)
        Rc 
= InStr(1, bIID, vbNullChar) - 1
        IID 
= Left$(UCase(bIID), Rc)

        
Select Case IID
            
Case IID_IDispatch
                
If ((dwEnabledOptions And dwOptionsSetMask) <> _
                    INTERFACESAFE_FOR_UNTRUSTED_CALLER) 
Then
                    Err.Raise E_FAIL
                    
Exit Sub
                
Else
                    
If Not m_fSafeForScripting Then
                        Err.Raise E_FAIL
                    
End If
                    
Exit Sub
                
End If

            
Case IID_IPersistStorage, IID_IPersistStream, _
            IID_IPersistPropertyBag
                
If ((dwEnabledOptions And dwOptionsSetMask) <> _
                    INTERFACESAFE_FOR_UNTRUSTED_DATA) 
Then
                    Err.Raise E_FAIL
                    
Exit Sub
                
Else
                    
If Not m_fSafeForInitializing Then
                        Err.Raise E_FAIL
                    
End If
                    
Exit Sub
                
End If
            
Case Else
                Err.Raise E_NOINTERFACE
                
Exit Sub
        
End Select
    
End If
End Sub

        这时客户机上IE已经可以正常安装我们的CAB包了。结果如下图:

image 

       总结下来,Windows XP SP2对ActiveX的限制变得更加严格,对基于微软技术的B/S开发造成了相当大的困难,期待有更好的解决方案出现。

 

注:如果是VB开发的ActiveX,要实现ISafeObject接口需要使用objsafe.tlb,找了很久,附上这个类型库

转载于:https://www.cnblogs.com/TonyJoule/archive/2009/03/04/1402871.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值