网站配置使用https访问

简单了解HTTPS、HTTP、SSL、TLS

  • http的连接很简单,是无状态的,无加密,也就是明文,数据都可以看到。

  • HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

  • SSL是基于HTTP之下TCP之上的一个协议层,是基于HTTP标准并对TCP传输数据时进行加密,所以HPPTS是HTTP+SSL/TCP的简称。

  • TLS(传输层安全)是更为安全的升级版 SSL。

IIS配置为HTTPS方式访问

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
访问https链接的时候可能会出现“不安全的链接”的错误提示,或者会提示“未签名的数字证书”。
在这里插入图片描述
不要慌!单击继续访问或者另一种报错下方有个高级选项,继续访问即可。IIS证书默认有效时间是一年哦

Tomcat配置为HTTPS访问

首先,网站要能够正常访问,需要配置JDK环境和Tomcat的环境变量,教程很多不多说。
进入JDK安装目录,以自己的目录为准,可以看到keytool工具,JDK中keytool是一个证书管理工具,可以生成自签名证书(即自己生成的证书,并不是官方生成的证书)。除非是很正式的项目,否则使用自己签发的证书即可,因为官方生成证书收费哟,在此目录空白位置按住shift键+鼠标右键,在此处打开命令窗口,或者直接运行cmd,输入如下命令:
在这里插入图片描述

cd C:\Program Files\Java\jdk-11.0.2\bin

使用keytool生成免费证书,默认有效时间是3个月,可以通过**-validity**设置有效时间:

keytool -genkey -alias tomcat -keyalg RSA -keystore C:\tomcat.keystore

在这里插入图片描述
注意:上面***你的名字与姓氏***使用你的域名或者IP,本地既作服务端又作客户端时,可以使用localhost,如果要测试在局域网访问则使用IP,当然有域名就使用域名,外网域名大家都可以访问。通过浏览器访问时就可以用https://192.168.1.111:8443这样的方式去访问。

查看证书

keytool -list -v -keystore C:\tomcat.keystore

在这里插入图片描述
配置tomcat
修改apache-tomcat-8.5.39\conf目录下的server.xml。
1、注释掉8080端口配置(可选,不注释的话使用http的8080端口也可以访问)

2、添加8443端口配置,也可以用443端口(443是https默认端口,通过浏览器访问时可以不写端口),将生成的证书路径和密码配置到

<Connector 	protocol="org.apache.coyote.http11.Http11NioProtocol"	
            port="8443" maxThreads="200"	
            scheme="https" secure="true" SSLEnabled="true"	                
            keystoreFile="C:\tomcat.keystore" 
            keystorePass="123456"	
            clientAuth="false" sslProtocol="TLS"/>

属性说明

clientAuth:设置是否双向验证,默认为false,设置为true代表双向验证

keystoreFile:服务器证书文件路径

keystorePass:服务器证书密码

3、浏览器访问,输入https://localhost:8443/
在这里插入图片描述
这个时候提示证书错误,因为客户端没有信任服务端证书,步骤参考双向认证的第5、6步,安装证书之后就不会再提示了。

配置tomcat为双向认证

上面已经配置了单向认证,接下来配置双向认证。在前述配置的基础上进行配置。先简单介绍下SSL双向认证机制:
客户端(通常是浏览器)带上自己的客户端证书(私钥,第7步)去请求服务器,服务器由于信任了客户端证书(第4步),那服务器收到客户端的证书,自然就能够解析出来,我认识你。然后就把我的宝贝(服务端证书,即公钥)返回给客户端,客户端又信任了服务端的证书(第6步),我也认识你,既然彼此认识呢。那咱们就可以说点悄悄话了。双向认证完成。其他人都不知道你的私钥和公钥,就算把你的请求都抓下来,也无法解析其中的数据。这就是https的这个"S",安全!

属性说明

truststoreFile:用来验证客户端证书的根证书,此例中就是服务器证书

truststorePass:根证书密码

1、修改server.xml文件,添加上述两个属性,并将clientAuth设置为true

<Connector 	protocol="org.apache.coyote.http11.Http11NioProtocol"	
                port="8443" maxThreads="200"	
                scheme="https" secure="true" SSLEnabled="true"	                
                keystoreFile="C:\tomcat.keystore" 
                keystorePass="123456"				
				truststoreFile="C:\tomcat.keystore"
                truststorePass="123456" 	
                clientAuth="true" sslProtocol="TLS"/>

2、服务端证书库已经在前文生成,现在生成客户端证书库

keytool -genkey -alias client -keypass 123456 -keyalg RSA -storetype PKCS12 -storepass 123456 -keystore C:\client.p12

在这里插入图片描述
3、导出客户端证书

keytool -export -alias client -keystore C:\client.p12 -storetype PKCS12 -keypass 123456 -file C:\client.cer

在这里插入图片描述
4、将生成的客户端证书导入到服务器的证书库,添加为一个信任证书。

keytool -import -v -file C:\client.cer -keystore C:\tomcat.keystore

在这里插入图片描述
添加之后再使用命令查看服务器证书库,可以看到两个证书信息。一个是服务器证书,一个是受信任的客户端证书。截图就省略了,太长了。

keytool -list -v -keystore C:\tomcat.keystore

5、导出服务端证书

keytool -keystore C:\tomcat.keystore -export -alias tomcat -file C:\server.cer

在这里插入图片描述
6、将服务端证书导入到客户端浏览器受信任的根证书中。
Internet选项>>内容>>证书>>受信任的根证书颁发机构>>导入,选择刚刚导出的服务端证书,或者直接双击server.cer安装证书,两种安装证书方式有一丢丢差异,但是最终结果是一样的,相信难不倒聪明的你。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
7、客户端浏览器安装客户端证书库。
安装之后,客户端浏览器请求的时候就会带上客户端证书(私钥)去访问服务器。
安装过程跟上面服务器安装过程类似,只不过这次我们需要将客户端证书库安装到"个人"下,需要输入之前设置的客户端证书库密码。
双击client.p12进行安装
在这里插入图片描述
在这里插入图片描述
也可以直接选择"根据证书类型,自动选择证书存储"。

双向认证完成,再也没有之前的证书错误提示了,真香!!!还不赶紧打开网页试一试!!!

浏览器输入https://192.168.1.111:8443,每次浏览器访问都需要手动确认发送客户端证书。
在这里插入图片描述
确定之后正常打开网页
在这里插入图片描述

强制http跳转到https,首先修改你的apache-tomcat-8.5.39\conf目录下的web.xml
在最后添加:

<!-- 强制SSL配置,即普通的请求也会重定向为SSL请求 -->  
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>SSL</web-resource-name>
            <url-pattern>/*</url-pattern><!-- 全站使用SSL -->
        </web-resource-collection>
        <user-data-constraint>
            <description>SSL required</description>
            <!-- CONFIDENTIAL: 要保证服务器和客户端之间传输的数据不能够被修改,且不能被第三方查看到 -->
            <!-- INTEGRAL: 要保证服务器和client之间传输的数据不能够被修改 -->
            <!-- NONE: 指示容器必须能够在任一的连接上提供数据。(即用HTTP或HTTPS,由客户端来决定)-->
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

在这里插入图片描述
是不是以为到这就万事大吉了?NO!NO!NO!
还记不记得前面说注释掉8080端口,也可以不注释,那你到底注释了没有呢?如果你注释了,那你有其他的http端口开着吗,是否重定向到8443端口了?没有的话,配置强制访问有什么意义。所以我就是在坑你!!!简单说一句,你设置了强制重定向,那么你就需要在server.xml配置你需要跳转的http端口,并设置redirectPort=“8443”,也就是说将你指定的http端口重定向到你的https端口。比如前面我不注释我的8080端口并重定向到了8443。那么我使用http://192.168.1.111:8080访问时就自动跳转到了https://192.168.1.111:8443。

tomcat对webservice进行权限验证

WebService鉴权方式以下几种:
1、对Web方法添加用户名和密码两个参数,在实现类中进行对其权限验证。

2、使用SoapHeader,将用户名和密码绑定到SoapHeader,在服务端添加拦截器,对SoapHeader进行拦截,获取其中的用户名密码进行权限验证。
这两种方式都是对客户端调用方法时的验证,还是能访问wsdl文件,如果要对wsdl文件的访问也加上用户权限验证,添加验证之后,wsdl地址的访问也需要用户明和密码才能访问,有以下两种方法:

方法一:

这里注意修改xml文件时使用的工具,用notepad++可以设置编码格式,那么你的中文注释使用UTF-8编码就能够识别,如果使用普通的记事本的话不能更改编码格式,部署tomcat会报错,xml文件解析不出来,虽然成功启动tomcat,但是在启动的时候它明确提示你这是严重的错误,当然你的URL肯定也是访问不了。所以最简单的方式就是在正式环境就别用中文注释了。
1、修改web.xml,添加如下:

<security-constraint>
	 <web-resource-collection>
	  <http-method>GET</http-method>
	  <http-method>POST</http-method>
	  <web-resource-name>tomcat protect page</web-resource-name>
	  <!-- /soap目录下的所有资源是受保护的 -->
	  <!-- 我的WebService地址/soap/CommonService?wsdl -->
	  <!-- url-pattern不能写/CommonService,必须写它的上一级目录,否则无法访问 -->
	  <url-pattern>/soap/*</url-pattern>
	 </web-resource-collection>
	 <auth-constraint>
	  <!-- 这里的myUserRole要与tomcat-user.xml中配置的role一致 -->
	  <role-name>myUserRole</role-name>
	 </auth-constraint>
</security-constraint>
<login-config>
	 <!-- 验证方式,可选的值为: "BASIC", "DIGEST", "FORM", "CLIENT-CERT" -->
	 <auth-method>BASIC</auth-method>
	 <!-- 使用的Realm名字,注意这里不能有空格 -->
	 <!-- 在客户端调用时使用类似setRealm("WEBSERVICELOGIN")函数时会用这个名字 -->
	 <realm-name>WEBSERVICELOGIN</realm-name>
</login-config>
<security-role>
    <description>myUserRole</description>
    <role-name>myUserRole</role-name>
</security-role>

如果不加最后security-role属性里面的内容,启动tomcat可能会出现警告:

WARNING [Catalina-utility-2] org.apache.catalina.startup.ContextConfig.validateSecurityRoles Security role name [myUserRole] used in an <auth-constraint> without being defined in a <security-role>

2、修改tomcat-user.xml

<role rolename="myUserRole"/>
<user username="myUser" password="myPassword" roles="myUserRole"/>

重启tomcat
在这里插入图片描述
客户端在访问时使用setUsername()和setPassword()两个函数传递用户名和密码进行验证,根据自己的客户端的确定调用的方法,基本上都是这两个函数。这个账号密码是在http协议头的authorization属性里面,不在SOAP协议的SoapHeader里面,切勿混淆,解密出来就是用户名和密码:
在这里插入图片描述

使用idea选择Java->Web Service Client创建基于axis的客户端调用:

    ((HelloServiceSoapBindingStub) service).setUsername("myUser");
    ((HelloServiceSoapBindingStub) service).setPassword("myPassword");

也可以不创建客户端,动态调用:

    call.setUsername("myUser");
    call.setPassword("myPassword");
方法二:

本方法基于springboot整合shiro框架,自己对shiro封装一个ShiroConfig配置类,主要代码如下:

/**
     * Shiro过滤器配置
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
    {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // Shiro的核心安全接口,这个属性是必须的
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 身份认证失败,则跳转到登录页面的配置
        shiroFilterFactoryBean.setLoginUrl(loginUrl);
        // 权限认证失败,则跳转到指定页面
        shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
        // Shiro连接约束配置,即过滤链的定义
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 对静态资源设置匿名访问,shiro按顺序验证
        filterChainDefinitionMap.put("/excelTemp/**", "anon");
        filterChainDefinitionMap.put("/favicon.ico**", "anon");
        filterChainDefinitionMap.put("/wootion.png**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/docs/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/ajax/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/wootion/**", "anon");
        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");

        //我的WebService
        filterChainDefinitionMap.put("/soap/**", "anon");
        // 退出 logout地址,shiro去清除session
        // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了,登出后跳转配置的loginUrl
        filterChainDefinitionMap.put("/logout", "logout");
        // 不需要拦截的访问
        //filterChainDefinitionMap.put("/login", "ssl,anon,captchaValidate");
        filterChainDefinitionMap.put("/login", "anon,captchaValidate");
        // 系统权限列表
        // filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());

        Map<String, Filter> filters = new LinkedHashMap<>();
        filters.put("onlineSession", onlineSessionFilter());
        filters.put("syncOnlineSession", syncOnlineSessionFilter());
        filters.put("captchaValidate", captchaValidateFilter());
        // 注销成功,则跳转到指定页面
        filters.put("logout", logoutFilter());
        //filters.put("ssl",sslFilter());
        shiroFilterFactoryBean.setFilters(filters);

        // 所有请求需要认证
        filterChainDefinitionMap.put("/**", "user,onlineSession,syncOnlineSession");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

这里面主要就是下面这句:

   //我的WebService
   filterChainDefinitionMap.put("/soap/**", "anon");

对我的webservice:/soap/的所有url进行拦截,这里使用的是anon匿名访问,也就是无验证,修改成authc就必须要求用户在访问时先在我的登录页面进行登录,否则无法访问。

使用tomcat时遇到的一些问题总结

1、要想使用tomcat8w.exe,需要注册服务否则提示指定服务未安装,在tomcat的bin目录运行命令service.bat install即可,注意版本问题,和下面一样,注册服务会绑定系统的java环境,在jdk1.8注册的服务,部署JDK11的项目会报错,修改系统环境变量还不行,还要删除服务重新在新环境下注册,删除服务使用sc delete+服务名。
2、tomcat出现部署失败,注意检查tomcat版本与JDK版本是否兼容(基础不牢,导致我犯下这个错误),首先是确认本身的运行环境tomcat与java版本的兼容性,其次是检查自己项目所使用的的java版本与当前系统环境变量设置的Java版本(如果自己有多个版本JDK),我有两个JDK版本分别对应两个不同的项目,一个用JDK1.8,一个用JDK11,我在系统环境变量里配置使用的JDK1.8,但是我启动使用JDK11的项目就会导致网页无法访问甚至报错,修改环境变量为JDK11恢复正常,同理,我在JDK11环境下启动使用JDK1.8的项目就会报部署的错,报错类似:

严重 [localhost-startStop-1] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start: 
 org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/roadgate]]
 严重 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Error deploying web application archive C:\Users\Administrator\Desktop\apache-tomcat-8.0.53\webapps\roadgate.war
 java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/roadgate]]

tomcat与所支持的Java版本对照表
在这里插入图片描述

3、IDEA出现编码问题,网上方法一大堆,也没搞明白,其实根本原因就是你各个源文件的编码不一致,有可能有的文件是你直接复制的别人的,而别人并没有使用你这种编码格式。解决办法最简单的就是把所有格式不一致的源文件使用notepad++(用什么工具修改看你心情,不固定)修改为统一的格式。
4、缓存警告:

WARNING [localhost-startStop-1] org.apache.catalina.webresources.Cache.getResource Unable to add the resource at [/WEB-INF/classes/static/excelTemp/20201102/LVSHCAAU6LE048629Ticket.xls] to the cache for web application [/roadgate] because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache

tomcat默认允许缓存且大小为10M,用于加载静态资源,如js、css、静态页面等,缓存大小根据自己的需要设置,在 tomcat/conf/context.xml 文件中增加如下内容:

<Resources cachingAllowed="true" cacheMaxSize="100000" />

本文所涉及源码下载

项目完整代码(含服务端及客户端)
客户端代码,方便没有C币的朋友参考:

package example;

import com.HelloServiceSoapBindingStub;
import com.HelloService_PortType;
import com.HelloService_ServiceLocator;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.apache.axis.message.SOAPHeaderElement;

import javax.management.remote.rmi.RMIConnection;

import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ServiceException;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;

import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;


//创建Java项目,勾选Web Service Client,选择Apache axis版本,创建后自动弹窗创建接口相关类及wsdl文件(com包下,包名自己取)

//基于axis框架的WebService客户端,还有基于cxf的
public class HelloWorldClient {
    public static void main(String[] argv) {
        clientCall();
        dynamicCall();
    }

    //使用需要生成wsdl文件,创建客户端(自动生成相关类代码)
    public static void clientCall() {
        try {
            HelloService_ServiceLocator locator = new HelloService_ServiceLocator();
            //RMIConnection service = locator.get();
            HelloService_PortType service = locator.getHelloServiceImplPort();

            //如果服务端部署到外部tomcat时对URL进行了拦截,并设置了账号密码,这个账号密码是在http协议请求头的authorization属性里面
            // (在tomcat-user.xml中配置用户名和密码,在web.xml中配置拦截URL),那就必须使用下面两行代码进行验证授权
            // If authorization is required
            ((HelloServiceSoapBindingStub) service).setUsername("myUser");
            ((HelloServiceSoapBindingStub) service).setPassword("myPassword");

            //服务端使用了拦截器,使用SOAPHeader进行身份验证
            SOAPHeaderElement header = new SOAPHeaderElement(new QName("timamaes"));
            SOAPElement element = header.addChildElement("username");
            element.addTextNode("admin");
            header.addChildElement("password").addTextNode("123456");
            ((HelloServiceSoapBindingStub) service).setHeader(header);
            //System.out.println(header);

            // invoke business method
            String result = service.sayHello("java web service client");
            System.out.println(result);
        } catch (javax.xml.rpc.ServiceException ex) {
            ex.printStackTrace();
        } catch (java.rmi.RemoteException ex) {
            ex.printStackTrace();
        } catch (SOAPException e) {
            e.printStackTrace();
        }
    }

    //不需要生成客户端,也不需要wsdl文件,动态调用
    public static void dynamicCall() {
        String url = "http://localhost:8080/myspringbootdemo/soap/api?wsdl";
        //String url = "http://localhost:8080/soap/api?wsdl";
        Service service = new Service();
        try {
            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(new URL(url));
            // WSDL里面描述的接口名称(要调用的方法)
            //QName中namespaceURI指的是自己WebService服务端设置的命名空间,即服务端@WebService注解的targetNamespace属性
            //Qname中localPart指的是服务端发布的WebService中的方法名
            call.setOperationName(new QName("http://services.myspringbootdemo.example.com",
                    "sayHello"));
            //跨平台调用加上这个
            //call.setUseSOAPAction(true);
            //call.setSOAPActionURI("http://services.myspringbootdemo.example.com/sayHello");
            // 接口方法的参数名, 参数类型,参数模式 IN(输入), OUT(输出) or INOUT(输入输出)
            //这里特别注意,如果服务端没有使用注解@WebParam(name="ParaName")方式为服务端方法的参数设置名字,
            //那么系统会自动使用arg0作为第一个参数名,arg1作为第二个参数名,依次类推。
            //如果使用了该注解,那么参数名就跟注解定义的名字一样。
            // 在wsdl文件中可以看到参数名到底是什么,在调用的时候一定要保证参数名称对应,否则会出现奇怪的错误
            call.addParameter("arg0", XMLType.XSD_STRING, ParameterMode.IN);

            // 设置被调用方法的返回值类型
            call.setReturnType(XMLType.XSD_STRING);

            //如果服务端部署到外部tomcat时对URL进行了拦截,并设置了账号密码,这个账号密码是在http协议头的authorization属性里面
            // (在tomcat-user.xml中配置用户名和密码,在web.xml中配置拦截URL),那就必须使用下面两行代码进行验证授权
            call.setUsername("myUser");
            call.setPassword("myPassword");

            //服务端使用了拦截器,使用SOAPHeader进行身份验证
            SOAPHeaderElement header = new SOAPHeaderElement(new QName("timamaes"));
            SOAPElement element = header.addChildElement("username");
            element.addTextNode("admin");
            header.addChildElement("password").addTextNode("123456");
            call.addHeader(header);

            // 设置方法中参数的值
            Object result = call.invoke(new Object[]{"qinqi"});

            System.out.println(result.toString());
        } catch (ServiceException | MalformedURLException | RemoteException | SOAPException e) {
            e.printStackTrace();
        }

    }
}

END!

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
配置Nginx以使用HTTPS使用域名进行访问,您需要执行以下步骤: 1. 获取SSL证书: - 您可以购买SSL证书,或者使用免费的证书颁发机构(如Let's Encrypt)来获取证书。 - 确保您获得了证书文件(通常是以.crt或.pem为扩展名的文件)和私钥文件(通常是以.key为扩展名的文件)。 2. 配置Nginx: - 打开Nginx的配置文件(通常是在/etc/nginx/nginx.conf或/etc/nginx/sites-available/default)。 - 在server块中添加以下配置: ``` server { listen 443 ssl; server_name your_domain.com; ssl_certificate /path/to/your_certificate.crt; ssl_certificate_key /path/to/your_private_key.key; location / { # 其他网站配置 } } ``` - 将`your_domain.com`替换为您的域名。 - 将`/path/to/your_certificate.crt`替换为您SSL证书的路径。 - 将`/path/to/your_private_key.key`替换为您的私钥文件的路径。 3. 配置HTTPHTTPS的重定向(可选): - 如果您希望将所有HTTP请求重定向到HTTPS,可以在HTTP server块中添加以下配置: ``` server { listen 80; server_name your_domain.com; return 301 https://$host$request_uri; } ``` - 将`your_domain.com`替换为您的域名。 4. 重新启动Nginx: - 保存并关闭配置文件。 - 在终端中输入以下命令以重新启动Nginx服务: ``` sudo service nginx restart ``` 现在,您应该可以通过使用您的域名以HTTPS访问您的Nginx服务器了。请确保您的域名已正确解析到您的服务器IP地址。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值