wse2.0实现webservice安全(转)

非常不错的wse2.0实现webservice安全的文章,讲的很详细,转自 http://blog.csdn.net/nealbzdn/,感谢原创作者。
 

WSE(Web Services Enhancements)是微软为了使开发者通过.NET创建出更强大,更好用的Web Services而推出功能增强插件。现在最新的版本是WSE2.0(SP2).本文描述了如何使用WSE2.0中的安全功能增强部分来实现安全的Web Services。WSE的安全功能增强实现的是WS-Security标准,此标准是WebService自己的安全协议,由IBM, BEA, Microsoft等联合制定,所以在.NET和Java系统上都可实现。

    我主要是根据WSE的文档说明和自己使用体会(其实多半也是按照文档画瓢,呵呵)而写,有错误之处请指出。另外,这是用的都是2.0,它与WSE1.0相比,变化很大,尤其在安全方面。

    还有一点注意,其实通过WSE实现安全有两种途径:一种就是我们下面要介绍的通过编写代码的方法;另外一种是直接编写策略文件(XML文档),这两种方法本质上都是通过对传递的SOAP消息进行设置,如增加用户消息,加解密,签名验证等,来实现安全功能的。但本人对第二种方法不太熟悉,也没时间研究,就不写了,呵呵。

 

一、使用用户名和口令验证Web Services调用者身份。

    原理很简单:客户端通过SOAP扩展,在SOAP消息中加入用户名和口令(明文或加密),发送给Web Services端;服务端接到消息后,同样通过扩展从消息上下文中得到用户名和口令,再进行身份验证和其他操作。下面是实现步骤:

    客户端:

    1.添加Microsoft.Web.Services2和客户端要访问的Web Services引用,没有什么好说的。当然,这两个引用是必须的,你可能还需要客户端需要添加其他引用。

    2.修改从Web Services引用生成的本地proxy类,这个类的代码在引用生成Reference文件中。从.NET开发环境右边的解决方案资源管理器里打开你要操作的Web Services引用文件夹,打开Reference.map节点,就可以看到Reference.cs或Reference.vb文件。如果你没有看到这些文件,可能是没有显示所有文件,你需要在解决方案资源管理器或命令菜单“项目”里设置“显示所有文件”。找到Reference文件后,打开它,在proxy类的声明处将类的继承父类改成Microsoft.Web.Services2.WebServicesClientProtocol.因为只有这样,proxy类才能访问WSE提供的SOAP扩展。注意,如果更新了Web服务的引用,则需要重新把继承类修改。

    3.通过UsernameToken类的实例添加用户名与口令。UsernameToken属于Microsoft.Web.Services2.Security.Tokens命名空间。假设Web Services的本地proxy类名称为WebServer.WebService,用户名为Username,用户口令为Userpwd,则代码可以如下所示(vb.net,下同):

    '生成本地proxy类实例

    Dim mywebserv as New WebServer.WebService

    '生成UsernameToken类实例,将用户名,用户口令和口令发送方式写在实例中

    Dim untoken As UsernameToken = New UsernameToken(Username, Userpwd, PasswordOption.SendPlainText)

    '设置SOAP消息有效期,以确减少消息即使被其他用户截获后重新使用的可能性为,这里设置为30秒,但要注意不同系统时钟同步的问题。

mywebserv.RequestSoapContext.Security.Timestamp.TtlInSeconds = 30

    '将UsernameToken实例加在SOAP消息上下文中

    mywebserv.RequestSoapContext.Security.Tokens.Add(untoken)

    '调用Web服务的方法WebMethod

    mywebserv.WebMethod

    这里需要说明口令发送方式的设置。口令发送方式为枚举型数据:SendNone,SendHashed,SendPlainText.分别为不发送口令,发送口令哈希值和发送口令明文,上面的例子是使用发送明文。如果选择SendNone,表示服务端不要验证口令,这个安全级别就很低,而且如果服务需要对传递的SOAP消息签名,则客户端要单独提供口令对其签名;SendHashed是指发送的是口令的SHA-1哈希值,这种情况下口令保护安全,这也是微软推荐的最好方式。但它需要服务器端通过编写代码和config文件设置自己来验证用户身份,具体验证方法在下面的服务器端设置会讲到;SendPlainText是口令以明文方式传递,如果采取这种方式,上述代码中的UsernameToken最好加密,否则口令很容易被截获。加密方法以后章节将详细论述;另外,如果服务器端选择让WSE自动根据Windows活动目录域的用户进行身份验证,那这里必须选择发送明文。

   

    服务端:

    1.首先在Web Services的配置文件Web.config里添加配置WSE的元素,这也是.NET开发的系统使用WSE最基本的一步。WSE文档上说如果服务的调用端是ASP.NET系统时才需要这一步的配置,如果是普通的Client程序则不需要加这个标识。可我测试发现即使调用端是Client程序,还是需要加这个配置。下面是完整的配置文档。

        <configuration>

              <system.web>

                <webServices>

                  <soapExtensionTypes>

                    <add type="Microsoft.Web.Services2.WebServicesExtension, Microsoft.Web.Services2,Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" priority="1" group="0"/>

                  </soapExtensionTypes>

                </webServices>

              </system.web>

    </configuration>

    当然,一般情况下你只需要在Web.config的<system.web>...</system.web>之间添加<webServices>...</webServices>部分。另外,add元素的数据最好写成一行,否则可能会出错。

    2.配置服务端的调用身份验证行为,这一步是可选的。

    如前所述,调用方发过来的SOAP消息中已加入了用户信息,服务端要做的工作是将这些信息解析出来,再根据一定规则对比验证,并返回结果。

上述处理过程也有两种选择:一是让WSE自动验证,我们自己的代码和配置文件再也不用做什么了。这种情况下,WSE在服务端收到调用方的SOAP消息后,从里面的UsernameToken中取出用户名和口令,这也是为什么前面提到过的自动验证下用户口令必须明文发送的原因,取出用户名和口令后,WSE是基于系统所在Windows域的用户进行判别和验证的。也就是说,WSE从活动目录里的用户列表遍历,寻找是否存在和所接收到的用户名/口令匹配的有效用户用户帐号,如果未找到匹配用户,则返回调用者未被授权的错误。由此可见,这种方法下应用系统及用户需要和Windows域紧密捆绑,缺乏灵活性并且不适合与已有业务系统对接。因此在实际应用中更多的应该是用下面第二种方法。

这种方法的核心是Web Services通过继承UsernameTokenManager类,并重载AuthenticateToken方法实现的。

    a.首先声明一个从UsernameTokenManager继承下来的类。

    Public Class CustomUsernameTokenManager

        Inherits UsernameTokenManager

    这里面有一个访问权限问题,为了使经过授权的程序集才能访问这个类,你还需要给它在声明时加上一些访问限定。因为能够访问非托管代码(UnmanagedCode)的程序集信任级别都是比较高的,所以可以要求能访问此类的程序集都是可以访问UnmanagedCode的。这样上面的声明就变成如下形式:

<SecurityPermission(SecurityAction.Demand,Flags:= SecurityPermissionFlag.UnmanagedCode)> Public Class CustomUsernameTokenManager

                    Inherits UsernameTokenManager

当然你也可以配置成其他权限要求,只要更改Flags的SecurityPermissionFlag枚举值即可。

b.在代码中重载AuthenticateToken方法。服务端接收到含有UsernameToken实例的SOAP消息后,WSE将UsernameToken反序列化,并调用VerifyToken方法,而VerifyToken方法在执行过程中又会调用AuthenticateToken方法,这个方法会返回一个口令值,WSE会拿它与UsernameToken中的口令进行对比。如果发送的口令为明文(UsernameToken.PasswordOption=SendPlainText),则直接对比;如果发送口令为哈希值(UsernameToken.PasswordOption=SendHashed),则WSE会对这个返回值做一个SHA-1哈希运算,再将结果与UsernameToken中的口令进行对比。如果不一致,则返回用户未被授权的错误。上述过程全部是自动完成的,因此我们要做的工作就是重载AuthenticateToken方法,在里面实现返回正确的用户口令,用于对比和验证。这其实就相当于WSE1.0里面的PasswordProvider.

重载AuthenticateToken方法实现的逻辑由系统根据具体要求来定,比如根据用户名去数据库里寻找相应的用户口令,或者从LDAP中等等。这里就照找了WSE文档上的例子,返回的口令和提交的用户名相同。

Protected Overrides Function AuthenticateToken(ByVal userName As UsernameToken) As String

' Ensure that the SOAP message sender passed a UsernameToken.

        If userName Is Nothing Then

            Throw New ArgumentNullException

        End If

               

        ' This is a very simple provider.

        ' In most production systems the following code

        ' typically consults an external database of (userName,hash)

        ' pairs. For this example, it is the UTF-8

        ' encoding of the user name.

Dim encodedUsername As Byte() = _

System.Text.Encoding.UTF8.GetBytes(userName.Username)

        Return System.Text.Encoding.UTF8.GetString(encodedUsername)

End Function

               

c.配置web.config文件,告知Web Services使用哪个类来验证用户身份。

首先在文件中加入标明使用WSE2的元素:

    <configuration>

        <configSections>

            <section name="microsoft.web.services2"

                      type="Microsoft.Web.Services2.Configuration.WebServicesConfiguration, Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

        </configSections>

    </configuration>

这里要注意的是一定要把<configSections>...</configSections>写到整个<configuration>...</configuration>里的最前面,否则会出现“响应内容类型为 "text/html;charset=utf-8",但应该是"text/xml"”的错误。

    其次配置使用UsernameTokenManager子类

    <configuration>

        <microsoft.web.services2>

            <security>

                <securityTokenManager xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"qname="wsse:UsernameToken" type="MyNamespace.CustomUsernameTokenProvider,MyAssemblyName,Version=2.0.0.0,Culture=neutral,PublicKeyToken=81f0828a1c0bb867" />

            </security>

        </microsoft.web.services2>

    </configuration>

    在这里面type属性的值要保持在一行,"MyNamespace.CustomUsernameTokenProvider必须是派生类有效的类层次名,MyAssemblyName为程序集名称。另外Version,Culture和PublicKeyToken等属性可以省略 。

    这样,我们就完成了在Web Service调用最基本的基于用户名/口令的验证。以后各项安全功能的实现都以它为基础。

 

二、使用用户名和口令对SOAP消息签名

    上述过程虽然实现了Web Services用户身份确认。但它不能保证Web Services接收到的SOAP消息就是所声明用户所发送的,因此在实际的应用中是还需要调用方对SOAP消息做一次签名,并将签名连同消息一起发送;服务端接收到消息后,除了验证用户身份外,还需要对其中的签名做一次认证。以确定消息在传输过程中没有被更改过,而验证的用户就是对消息签名的用户。

    客户端:

    只需要在原有客户端SOAP消息中添加签名即可,如下所示,黑体为新加代码:

    mywebserv.RequestSoapContext.Security.Tokens.Add(untoken)

    mywebserv.RequestSoapContext.Security.Elements.Add(New _

MessageSignature(untoken))    

mywebserv.WebMethod

    上述代码就是客户端根据UsernameToken的实例生成一个签名,然后把签名加在SOAP消息里,具体是WS-Security扩展的SOAP消息头。

    服务端:

    其实服务端无需改动什么。只要客户端发送的SOAP消息里面包含了签名,服务端就会自动验证签名的有效性。服务端首先验证用户名/口令,然后使用客户端传递的用户名和自己获得的口令(WSE自动从Windows活动目录中获得,或者通过重载的AuthenticateToken的方法)对签名进行验证。如果验证失败,说明消息在传递过程中被更改过或者不是当前调用用户所签,返回相应错误。

    WSE的帮助文档上这一块加了一个判断SOAP里是否包含签名的函数,通过它可以获得签名的一些相关信息,并不是必须的。有兴趣的朋友可以自己去看。

 

三、使用证书验证身份并对SOAP消息签名

    使用用户名/口令存在固有缺点,因此在某些安全要求较严格的系统中我们还需要使用证书来完成对用户身份的验证。关于PKI/CA的基础知识这里就不介绍了,大家可以去看相关资料。

    首先我们需要配置服务端保证WSE可以访问证书及其私钥。(至于证书的申请,管理和使用属于基础知识,在这就不讲了)这里主要是在Web Services端设置,以保证服务端可以自动完成某些功能,还无需用户干预。在Web.config文件添加如下<x509>元素(黑体部分):

<configuration>

  <microsoft.web.services2>

    <security>

      <x509 storeLocation="CurrentUser" />

    </security>

  </microsoft.web.services2>

</configuration>

storeLocation属性为WSE可访问的证书存储。它可选的值有两项:“LocalMachine”和“CurrentUser”,分别表示本机证书存储和当前用户证书存储。这里用的是CurrentUser,而storeLocation缺省值是LocalMachine.另外几个属性的配置如下: verifyTrust,是否验证所用证书的证书链有效性,缺省为true;allowTestRoot:验证证书链过程中是否认为测试根CA所签发证书有效,这个参数在verifyTrust为true时才有效,缺省为false;allowRevocationUrlRetrieval,是否在线验证证书是否被吊销,在verifyTrust为true时才有效,缺省为true;allowUrlRetrieval,是否在线验证证书链有效性,allowRevocationUrlRetrieval,是否在线验证证书吊销状态。

 

    客户端:

    第1、2步与第一节使用用户名/口令的步骤基本相同。但这里也要多加一个引用:Microsoft.Web.Services2.Security.X509

3.编写代码取得要使用的证书。我这里用了一个listview控件显示当前用户证书存储里的个人证书,以供用户选择。你当然也可以象WSE文档上那样利用证书的属性去定位需要使用的证书。Listview控件名称为lv_certlist,它有两列:证书持有者主体和颁发者名称。

Dim cert As X509Certificate

        Dim lvitem As ListViewItem

        '从当前用户证书存储中打开个人证书库

  certstore = X509CertificateStore.CurrentUserStore(X509CertificateStore.MyStore)

        certstore.Open()

        lv_certlist.Items.Clear()

        '遍历证书,写到listview控件里

        For Each cert In certstore.Certificates

            lvitem = lv_certlist.Items.Add(cert.GetName)

            lvitem.SubItems.Add(cert.GetIssuerName)

            lvitem.Tag = lvitem.Index

        Next cert

4.选择所选择的证书生成X509SecurityToken的实例,它和前面的UsernameToken一样是SecurityToken的子类。

        Dim cert As X509Certificate

        Dim certToken As X509SecurityToken

        Dim result As String

        cert = certstore.Certificates(lv_certlist.SelectedIndices(0))

        ’判断所选择证书是否支持签名,并且私钥是否存在

        If cert.SupportsDigitalSignature And Not (cert.Key Is Nothing) Then

            '遍历证书,写到listview控件里

certToken = New X509SecurityToken(cert)

            Dim mywebserv As New WebServer.WebService

mywebserv.RequestSoapContext.Security.Timestamp.TtlInSeconds = 30

'添加包含证书信息的X509SecurityToken

mywebserv.RequestSoapContext.Security.Tokens.Add(certToken)

'使用证书对SOAP消息签名,并将结果写在消息中

            mywebserv.RequestSoapContext.Security.Elements.Add(New _

MessageSignature(certToken))

'调用Web服务的方法

            mywebserv.WebMethod

        End If

 

    服务端:

    和验证使用用户名/口令签名的消息类似,服务端也同样自动验证签名有效性。同时,服务端会根据web.config文件中<x509>元素里的属性设置来对证书的有效性进行验证。如果验证失败,则返回相应错误。

四、使用用户名和口令对SOAP消息加密

    前面第一节讲过,如果UsernameToken实例中的口令是明文,那最好将UsernameToken加密发送。在第一节客户端代码中做如下改动,黑体代码为新加:

mywebserv.RequestSoapContext.Security.Tokens.Add(untoken)

    mywebserv.RequestSoapContext.Security.Elements.Add(New _

Microsoft.Web.Services2.Security.EncryptedData (untoken))    

mywebserv.WebMethod

    上述代码就是客户端根据UsernameToken的对SOAP消息加密,然后把密文加在SOAP消息里,具体是WS-Security扩展的SOAP消息头

    服务端自动对消息解密。服务端首先验证用户名/口令,然后使用客户端传递的用户名和自己获得的口令(WSE自动从Windows活动目录中获得,或者通过重载的AuthenticateToken的方法)对解密数据。如果失败,返回相应错误。

    WSE的帮助文档上这一块同样加了一个判断SOAP是否加密的函数。

 

五、使用证书对SOAP消息加解密

    这个略微复杂一些。根据PKI非对称加解密原理,对消息加密的客户端需要事先得到作为接收方的服务端的证书公钥,而服务端必须保证可以访问其证书对应的私钥。因此我们首先要在服务端选择设置好它所使用的证书,原则就是使服务端能够随时并自动访问其证书对应的私钥。

    对于基于ASP.NET开发的Web Services,需要给它运行时的缺省用户赋予访问证书私钥的权限。运行在IIS 6.0上的Web Services缺省用户是Network Service,其他情况下用户账户由machine.config文件里<processModel>元素的userName属性决定,缺省情况下是“machine”,它等同于ASPNET账户。添加步骤如下:运行WSE 2.0自带的X.509 Certificate tool(开始---程序---Microsoft WSE 2.0---X.509 Certificate tool),选择并打开WSE要访问的证书。打开后,“Private Key File Name”文本框里会显示证书所对应私钥文件的名称,Private Key File Folder”文本框里会显示私钥文件的路径。单击“Private Key File Properties”打开文件属性对话框,可以在安全属性页里添加被授权访问的Network Service或ASPNET用户账户。

    如果打开证书后发现私钥文件不存在或不可访问,说明此证书有问题或者私钥受保护,比如有口令保护或者存储在安全外设中,不能被Web Services随时自动访问,因此也就不适用。

    对于Web Services,如果使用的用户是缺省的ASPNET,那最好选择本机存储(LocalMachine Store)里的证书。因为ASPNET这个用户是安装ASP.NET时自动生成的,它的口令是没有办法访问的。如果证书包含在当前用户存储(CurrentUser Store)中,服务端很可能就访问不到私钥。

    服务端设置好证书后,接下来就要使客户端得到这个证书和公钥。具体的方法和你的业务系统和应用需求有关系,你可以把它放在网页上让用户事先下载安装;如果应用在局域网环境,可以让客户端去LDAP或CA里取得。

    客户端做如下改动:

mywebserv.RequestSoapContext.Security.Tokens.Add(certToken)

SOAP消息中添加加密结果

  mywebserv.RequestSoapContext.Security.Elements.Add(New _

  Microsoft.Web.Services2.Security.EncryptedData(certToken))

mywebserv.WebMethod

  服务端接收到加密后的SOAP消息后,自动使用相应私钥解密。如果失败,返回相应错误。

可以看出,使用证书加解密消息的难点在于证书的选择和配置,尤其是消息接收端。

 

WSE除了支持上述用户名/口令,X509证书两种令牌外。还支持Kerberos Ticket,安全上下文令牌(Security Context Token)和用户自定义令牌。Kerberos Ticket好象是WSE自己加的内容,标准的WS-Security里没有,而且只在Windows XP SP1/SP2,Windows2003上支持。安全上下文令牌需要一个上下文令牌服务生成。而用户自定义令牌的核心是由SecurityToken派生一个用户自己的令牌类,完成各种安全功能。总之WSE就是使用这种基于令牌和扩展SOAP消息来实现Web Services安全的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Microsoft WSE 2.0 SP3是微软的一个安全性和互操作性解决方案,它提供了用于开发和部署Web服务的工具和方法。安装Microsoft WSE 2.0 SP3的步骤如下: 1. 下载安装程序:首先,您需要从微软官网或其他可靠来源下载Microsoft WSE 2.0 SP3的安装程序。 2. 运行安装程序:找到下载的安装程序文件,并双击运行它。它会打开安装向导。 3. 阅读许可协议:在安装向导中,您将看到许可协议的内容。请阅读并接受许可协议,然后点击"下一步"继续安装。 4. 选择安装位置:接下来,您需要选择WSE 2.0 SP3的安装位置。您可以选择接受默认位置,或自定义安装位置。点击"下一步"继续。 5. 完成安装:在最后一步中,您可以选择是否创建桌面快捷方式,并点击"安装"开始安装过程。 6. 等待安装完成:安装过程可能需要一段时间,具体时间取决于您的计算机性能和网络速度。请耐心等待直到安装完成。 7. 检查安装:安装完成后,您可以打开所安装的目录,验证Microsoft WSE 2.0 SP3是否已成功安装。 总结: 安装Microsoft WSE 2.0 SP3的步骤包括下载安装程序、运行安装程序、阅读许可协议、选择安装位置、完成安装和检查安装。请确保在安装过程中保持稳定的互联网连接,并根据安装向导的指示进行操作。希望这些步骤对您有帮助! ### 回答2: Microsoft WSE 2.0 SP3是微软提供的一个Web服务扩展,用于增强和加强Web服务的安全性和可靠性。要安装Microsoft WSE 2.0 SP3,可以按照以下步骤进行操作: 首先,确保已经满足安装要求。Microsoft WSE 2.0 SP3只能安装在支持Microsoft .NET Framework 2.0的操作系统上。因此,在安装之前,请确保您的计算机已经安装了.NET Framework 2.0或更高版本。 其次,下载Microsoft WSE 2.0 SP3安装程序。您可以在微软的官方网站上找到安装程序的下载链接。下载完成后,双击安装程序运行安装向导。 然后,按照安装向导的指示进行操作。首先,选择安装目录,通常建议使用默认的安装目录。然后,阅读许可协议并同意。接下来,选择要安装的组件。默认情况下,所有组件都会被安装,您也可以根据自己的需要进行选择。最后,点击“安装”按钮开始安装。 安装过程可能会需要一些时间,取决于您的计算机性能和网络速度。安装完成后,您可以看到安装成功的提示信息。此时,您可以关闭安装程序并重新启动计算机。 完成上述步骤后,Microsoft WSE 2.0 SP3将成功安装在您的计算机上。您现在可以在您的项目中使用WSE 2.0 SP3提供的各种强大的安全性和可靠性功能来增强和保护您的Web服务。 需要注意的是,Microsoft WSE 2.0 SP3已经不再支持并且已经过时。微软推荐使用更高版本的Web服务技术和工具,如Windows Communication Foundation(WCF)。因此,在开发新的Web服务项目时,建议使用最新的微软技术来获得更好的性能和功能。 ### 回答3: Microsoft WSE (Web Services Enhancements) 2.0 SP3 是一个为微软开发的 Web 服务提供增强功能的扩展。要安装 Microsoft WSE 2.0 SP3,您可以按照以下步骤进行操作: 1. 首先,确保您的计算机上已安装 .NET Framework 2.0。WSE 2.0 SP3 是构建在 .NET Framework 2.0 上的,所以在安装 WSE 2.0 SP3 之前必须先安装 .NET Framework 2.0。 2. 下载 Microsoft WSE 2.0 SP3 安装程序。您可以在微软官方网站上搜索并下载最新版本的 WSE 2.0 SP3 安装程序或从可信任的第三方软件下载网站获取。 3. 运行下载的安装程序。双击下载的安装程序文件,然后按照安装向导的提示进行操作。请注意,在安装过程中可能需要管理员权限。 4. 阅读并接受许可协议。在安装向导中会显示许可协议的内容。请仔细阅读并理解协议条款,如果同意协议,选择相应的选项继续安装。 5. 选择安装选项。在安装向导中,您可以选择安装 WSE 2.0 SP3 的位置和其他选项。按照自己的需求进行选择,然后继续安装。 6. 等待安装完成。安装程序将复制文件、注册组件和设置配置信息。请耐心等待安装过程完成。 7. 检查安装结果。安装完成后,您可以在计算机的安装目录中找到 WSE 2.0 SP3 的文件文件夹。您还可以检查计算机的控制面板中是否存在 WSE 2.0 SP3 的相关项。 通过上述步骤,您应该可以成功安装 Microsoft WSE 2.0 SP3。如果在安装过程中遇到任何问题,您可以查阅官方文档或在论坛或社区寻求帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值