session机制详解(thinkphp)

3 篇文章 0 订阅
1 篇文章 0 订阅
  1. 1 什么是会话控制
  2.     出现原因:http是无状态协议的,每次都是不同的服务器请求,无法维护两个请求事务之间的关系.
  3.     会话控制:能够在网站中跟踪一个变量,通过对变量的跟踪,就可以使多个请求事物之间建立联系,根据授权和用户身份显示不同的内容,不同页面
  4.     cookie:是服务器设置在客户端的文本文件,保存客户端得个人信息.
  5.  2 会话跟踪技术
  6.     1 隐藏表单域
  7.     2 url重写
  8.     3 cookie技术
  9.     4 session技术
  10.     
  11.     隐藏表单技术:
  12.         <input type="hidden" name="name" value="设置隐藏值">,在gethuopost方法中指定指定有关消息的会话名称和值
  13.         
  14.     url(统一资源定位)重写:
  15.         将唯一会话的id添加到url结尾,来进行标识
  16.         http://www.lampbrother.net?id=1000
  17.     cookie:将唯一的会话id存放在客户端
  18.     session:将唯一的会话id存放在服务器端
  19.  2 会话跟踪方式
  20.     第一:通过url传递参数,使用超链接或者header()函数
  21.     第二:使用隐藏表单域,提交给php脚本
  22.     第三:使用Cookie将用户的信息存储在客户端文件中
  23.     第四:使用Session将用户的信息存储在服务器端的信息存储在服务器端
  24.     
  25.  4 Cookie:
  26.     1 Cookie的介绍:
  27.         1 cookie是在http协议下,服务器或脚本在客户端保存维护信息的一种方式
  28.         2 cookieweb服务器保存在客户端的一个很小的文本文件,保存客户端的信息,提高网页的处理效率,降低服务器负担
  29.         3 cookie保存在客户端,通常在浏览器的cookie临时文件夹中,可以手动的删除.如果cookie太多超过系统的允许范围,系统将自动删除
  30.     
  31.     2 cookie的工作原理
  32.          1 当用户访问基于php技术的网站时,在php中可以使用setcookie()函数生成一个cookie,系统经过处理,将cookie发送到客户端并保存在C:\Documents and Setting\用户名\Cookies目录下
  33.         2 cookiehttp标头的一部分,在它之前不能有任何输出空格和换行都不可以
  34.         3 当客户端再次访问网站时,浏览器会自动把cookie目录下与该站点对应的cookie信息发送到服务器,服务器将自动把客户端传来的cookie转化成php的变量,.php5中存放在$_COOKIE全局数据中
  35.         4 接受和处理cookie.使用$_COOKIE获取
  36.     
  37.         Setcookie()为头信息设置,在此之前不能有任何输出
  38.         boolsetcookie( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure = false [, bool $httponly = false ]]]]]] )
  39.         Name:调用名为cookienamecookie 
  40.         value :name对应的值
  41.         exprice :设置cookie的过期时间和日期,用一个标 准的Unix时间标记,可以用time()函数取得,以秒为单位. 
  42.         path :服务器端的有效路径,设置为“/”表示这个域中所有数组都可以被访问读取。 
  43.         Domain:设定cookie有效域名 
  44.         secure :指明cookie只能通过安全的https传送, 设为true时只能通过安全的https,默认为false.即设置是否仅在https安全连接时才发送cookie到客户端:0 1
  45.     
  46.         删除cookie:
  47.             1 调用一个参数名为已经存在的cookied的名称,则删除就会删除cookie
  48.             2 设置cookie的失效时间为time()或者time()-1
  49.     
  50.         注意:当cookie被删除时,它的值在当前页面仍然有效.如果要把cookie设置成在浏览器关闭后就失效.那么可以吧expiretime的值设为0,或者不设此值
  51.     
  52.         /*设置cookie*/
  53.         $time=time()+3600;//设置时间为一个小时
  54.         //保存变量
  55.         setcookie('username','admin',$time);
  56.         setCookie('password','123456',$time);
  57.     
  58.         //保存数组
  59.         setCookie("cookie[one]",'coo1',$time);
  60.         setCookie("cookie[two]",'coo2',$time);
  61.         /*删除cookie*/
  62.         //方式1:设置值为空
  63.         setCookie('username',"");
  64.         setCookie('cookie[one]',"");
  65.         //方式1:设置过期时间
  66.         setCookie('password',"coo1",time()-1);
  67.         setCookie('cookie[two]',"coo2",time()-1);
  68.         if(isset($_COOKIE)){
  69.         }
  70.     3 COOKIE的注意事项
  71.         1 setcookie()之前不能有任何的输出,空白和空格也不行(Setcookie()为头信息设置)
  72.         2 setcookie()之后在当前页面echo时不会输出,必须刷新或到下一个页面才会输出
  73.         3 不同浏览对cookie的处理不同,客户端可以禁用cookie,而且对浏览器的数量有限制.一个浏览器可以最多创建300cookie,每个不能超过4kb,每个站点最多设置20
  74.         4 避免过度依赖cookie,因为客户端会禁止掉cookie
  75.     
  76.  7 session
  77.     1 什么是session?
  78.         1 session从用户访问页面开始,到断开与网站的连接为止,形成一个会话的生命周期.在会话期间,分配客户唯一的一个sessionID,用来标识当前用户,与其他用户进行区分
  79.         2 session会话时,session会分别保存在客户端和服务器端得两个文职,对于客户端:使用临时的cookie保存(cookie的名称为PHPSESSID)或者通过url字符串的形式传递.服务器端也以文本的形式保存在指定的session目录中
  80.         3 session通过id接受每一次访问的请求,从而识别当前用户,跟踪和保持用户的具体资料,以及session变量,可在session中国存储数字或文字资料.比如session_name.这些信息都保存在服务器端
  81.         4 sessionID可以作为会话信息保存到数据库中,进行session持久化.这样可以跟踪用户的登陆次数,在线与否,在线时间
  82.     2 cookiesession的区别:
  83.         相同点:都可以在解决http无状态的问题,使同一个客户端在访问网站的多次请求中,可以保存,设置信息,并且在整个web应用中共享
  84.         
  85.         不同:
  86.         cookie的信息保存在客户端
  87.         session:保存在服务器端
  88.     
  89.         联系:当使用基于cookiesession时,session DI一般保存在cookie
  90.     3 设置session
  91.         1 开启会话
  92.             session_start()        功能 : 1开始一个会话,2 返回已经存在会话
  93.             说明:这个函数没有参数,且返回值为true,如果使用基于cookiesessin,那么在session_satrt()之前不能有任何的输出,包括空白
  94.     
  95.         2 注册会话
  96.             php5 使用$_SESSION['KEY']=VALUE方式,类似于GET,POST,COOKIE
  97.     
  98.         3 使用会话之前必须session_start()启动会话,这样就可以使用$_SEESION超全局数组访问变量了
  99.             判断是否设置session
  100.             if(isset($_SESSION))...;
  101.         
  102.         如果在php.inisession.auto_start=1;开启,则在每个页面执行session_start(),不需要手工设置.
  103.         缺点:不能将对象放入session
  104.         
  105.         //开启一个session会话,或者返回已经存在的session
  106.         session_start();
  107.         //这只session
  108.         $_SESSION['USER']='admin';
  109.         $_SESSION['username']='admin_root';
  110.         //获得session_id()
  111.         //1 PHPSESSID
  112.         echo $_COOKIE['PHPSESSID'].'<br>';
  113.         //2 session_name()
  114.         echo $_COOKIE[session_name()].'<br>';
  115.         //3 session_id()
  116.         echo session_id().'<br>';
  117.     4 销毁session
  118.         
  119.         注销变量:
  120.             1 unset($_SESSION['XXX']):用于删除单个session变量
  121.                 注意:不要使用unset($_SESSION),此函数不可用,会删除全局的$_SESSION销毁
  122.         
  123.             2 $_SESSION=array():删除多个session变量
  124.             3 session_unset():删除所有的session变量
  125.         销毁session_destroy():结束当前的会话,并清空会话中的所有资源.该函数不会unset(释放)和当前session相关的全局变量,也不会删除客户端的session cookie
  126.                 //返回已经存在的session
  127.                 session_start();
  128.     
  129.                 //清空session值
  130.                 $_SESSION=array();
  131.     
  132.                 //如果是基于Cookie的session,则清空cookie中的session_id()
  133.                 if(isset($_COOKIE[session_name()])){
  134.                     //  '/':在php.ini中年的cookie.path='/';
  135.                     setCookie($_COOKIE[session_name()],'',time()-3600,'/');
  136.                 }
  137.                 //销毁session
  138.                 session_destroy();
  139.             注:php默认的session是基于cookie的,如果要删除cookie的话,必须借助setcookie()函数
  140.         
  141.     5 保存session数据
  142.         1 保存基本数据类型
  143.         2 保存数组
  144.         3 保存对象
  145.         session_start();
  146.         //存取标量
  147.         $_SESSION['USER']='ADMIN';//STRING
  148.         $_SESSION['COUNT']=10;//INT
  149.         $_SESSION['PRICE']=99.99;//FLOAT
  150.         $_SESSION['IS_GOOD']=true;//BOOLEAN
  151.         //存取数组
  152.         $_SESSION['USER_INFO']=array('username'=>'root','password'=>123456);
  153.         //存取对象
  154.         class Person{public $name='admin';public $age=23;    }
  155.         $_SESSION['OBJ']=new Person;
  156.         
  157.         函数:
  158.         1 session_id():用于获取或取得当前的session的唯一标识符号SID,php5中既可以附加载url取得当前会话的session_idsession_name
  159.             SID:即使是一个字符串session_name()=session_id();
  160.             解释:
  161.             a 如果session_id()有具体指定的值得话,将取代当前的session_id值.当cookie没有被禁用时,如果指定了一个session_id()值,每次启动session_start()都会网客户端发送一个cookie值.不论当前SESSION_ID值是否与指定值相等
  162.             b 如果session_id()没有指定的值,则返回当前的SESSIONID,当前会话没有开启则返回空字符串
  163.             c 使用该函数必须在session_start()之前
  164.             <?php
  165.                 //在session_start()之前设置session_id()
  166.                 session_id('lamp');
  167.                 session_start();
  168.                 echo '当前的session_id()为:'.session_id().'<br>';//输出lamp
  169.             ?>
  170.         
  171.         2 session_regenerate_id():该函数更换当前的session_id,但不改变当前的session信息
  172.             返回值:bool
  173.             session_id:命名规则[a-z, A-Z, 0-9 and '-,' ]
  174.             //设置session_id=old_session[a-z, A-Z, 0-9 and '-,' ]
  175.             session_id('old-session');
  176.             $old_session_id=session_id();
  177.     
  178.             session_start();
  179.             //更改session_id=new_session
  180.             session_regenerate_id('new-session');
  181.             $new_session_id=session_id();
  182.             $_SESSION['USER']='ADMIN';//STRING
  183.             echo '原来的session_id:'.$old_session_id.'<br>';
  184.             echo '新的的session_id:'.$new_session_id.'<br>';
  185.             print_r($_SESSION);
  186.         3 session_name():获取或者更改当前的session_name,注意:不能只有数字组成,必须至少包含一个字母,否则每时每刻会生成新的session_id
  187.         
  188.             注意: session_id()和session_name()都要在session_start()之前设置
  189.             session_id('lamp2012');
  190.             session_name('mySession');
  191.             session_start();
  192.             $_SESSION['USER']='ADMIN';//STRING
  193.             echo 'session_id:'.session_id().'<br>';
  194.             echo 'session_name:'.session_name().'<br>';
  195.             print_r($_SESSION);
  196.          
  197.     6 session跨页传递的三种问题:
  198.         1 客户端禁用了cookie
  199.         2 浏览器出现了问题无法存储cookie
  200.         3 php.ini中的session.user_trans_sid=0或者编译时没有打开--enable-trans-sid选项
  201.         解决的三条途径:
  202.         1 php.ini中开启session.user_trans-sid=1,或者编译时打开--enable-trans-sid选项,让php自动跨页传递session_id
  203.         2 手动通过url传值,隐藏表单传递session_id
  204.             <a href="index.php?<?php echo SID?>">sid</a>
  205.             <a href="index.php?<?php echo session_name().'='.session_id()?>">sid</a
  206.         3 用文件,数据库等形式保存sessin_id,在跨页过程中手工调用
  207.             
  208.     7 持久化session
  209.         1 请求结束后所有的注册变量都会自动被序列化(为了方便保存到服务器端得会话文本文件中),获取的时候在进行还原
  210.         手动编码:
  211.         session_encode():序列号-编码
  212.         session_decode():还原-解码
  213.         
  214.         警告:有些类型的数据不能被序列化因此也就不能保存.包括resource变量和有循环引用的对象
  215.     9 配置会话控制
  216.         session.auto_start=0;//在请求启动时初始化
  217.         session.auto_start=0;//无需每次手动sessin_start(),不过该选项有一些限制,不能将对象放入会话,因为类的定义必须在会话之前加载在会话中重建对象
  218.         session.cache_expire=180;//设置缓存中的会话过期时间在n分钟后
  219.         session.cookie_lifetime=0;//设置按秒记的cookie的保存时间,0表示知道浏览器被重启
  220.         session.cookie_path=/;//cookie的有效路径
  221.         session.cookie_domain=;//cookie的有效域
  222.         session.name=PHPSSESID;//又在cookie里的session_name()
  223.         session.save_hander=files;//用于保存/取回数据的控制方式
  224.         session.save_path=/tmp;//在save_handler设为文件是传给控制器的参数,这是数据文件的保存路径
  225.         session.user_cookie=1;//是否使用cookies
  226.         
  227.         session.gc_maxlifetime=40;//指定过了多少秒之后数据就会被视为“垃圾”,并被清楚
  228.     
  229.         session.gc_probability=1//
  230.         session.gc_divisor=100;//这两个合起来就是启动gc进程管理概率的,在session初使化时(session_start())
  231.             session.gc_probability/session.gc_divisor:1/100,在session_start100次,有一次的概率删除垃圾文件
  232.     10 用文件保存session信息
  233.         1: php.ini中的session.save_handlercookie保存方式选项user    
  234.         2: 设置session操作中的回调函数,在session_start()之前使用session_set_save_handler('open','close','read','write','destroy','gc');
  235.         3: 开启session_start();
  236.             函数解析:
  237.             open($session_path,$session_name):在session_start()时启动,返回true
  238.             close():session_close()和session_destroy()时调用,return true
  239.             read($session_id):session_start()时和从$_SESSION取值的时调用,return true
  240.             write($session_id,$session_data):在session_write_close()强制将数据写入到$_SESSION全局数组中时调用,return true;
  241.             destroy($session_id):在执行session_destroy()自动调用,return true
  242.             gc($session_gc_lifetime):在执行session_start().read(),write()时自动调用,return true
  243.         
  244.         //参数:$save_path,$session_name
  245.         function open($save_path, $session_name){
  246.             //设置全局的session信息保存路径
  247.             global $sess_save_path;
  248.             //为session的保存路径赋值
  249.             $sess_save_path=$save_path;
  250.             return true;
  251.         }
  252.         //session_write_close()和session_destroy()时调用
  253.         function close(){
  254.             //在销毁和关闭写入时,不进行任何操作,返回true
  255.             return true;
  256.         }
  257.         //在session_start(),$_SESSION,将session数据读取到$_SESSION中时
  258.         //参数:session_id
  259.         function read($id){
  260.             //获得全局的session保存路径
  261.             global $sess_save_path;
  262.             //拼接所需的文件路径名称
  263.             $sess_file=$sess_save_path.'/king_'.$id;
  264.             //返回文件的信息,没有文件时返回false
  265.             return    (string)@file_get_contents($sess_file);
  266.         }
  267.         //结束时和session_write_close()强制将SESSION数据防止在$_SESSION全局变量时
  268.         function write($id,$sess_data){
  269.         
  270.             global $sess_save_path;
  271.             $sess_file=$sess_save_path.'/king_'.$id;
  272.             //以w模式打开文件
  273.             if($fp=@fopen($sess_file,'w')){
  274.                 session信息写入指定的资源中
  275.                 $return=fwrite($fp,$sess_data);
  276.                 fclose($fp);
  277.                 return $return;
  278.             }else{
  279.                 return false;
  280.             }
  281.         }
  282.         //在destroy时调用
  283.         function destroy($id){
  284.             global $sess_save_path;
  285.             $sess_file=$sess_save_path.'/king_'.$id;
  286.             //删除session路径下指定的session信心
  287.             return @unlink($sess_file);
  288.         }
  289.         //在session_start(),read(),write()时
  290.         function gc($maxlifetime){
  291.             global $sess_save_path;
  292.             //glob — 寻找与模式匹配的文件路径,返回数组
  293.             //将路径写的所有超过gc生命周期的文件删除
  294.             foreach(glob($sess_save_path.'/king_*') as $filename){
  295.                 if(filemtime($filename)+$maxlifetime < time()){
  296.                     @unlink($filename);
  297.                 
  298.                 }
  299.             }
  300.                 return true;
  301.         }
  302.         @session_set_save_handler('open','close','read','wite','destroy','gc');
  303.         @session_start();
  304.     11 session信息保存到数据库
  305.         sql:测试表
  306.         create table session(
  307.             PHPSSESID char(32),    //session_id
  308.             update_time int(10),    //文件的gc_maxlifetime
  309.             client_ip char(15),    //客户端ip地址
  310.             data text)    //session信息
  311.         1:设置session.save_handler=user;//自定义session存储方式
  312.         2 session.gc_maxlifetime=time;//gc回收垃圾的时间
  313.         3 session_start()之前调用session_set_save_handler('open','close','read','write','destroy','gc');
  314.         4 session处理类,静态属性和方法
  315.         5 开启session_start();
  316.         <?php
  317.             //session_set_save_handler
  318.             class Session{
  319.                 private static $handler=null;//传进来的pdo句柄
  320.                 private static $client_ip=null;//客户端ip
  321.                 private static $lifetime=null;//生存时间(session.gc_maxlifetime)
  322.                 private static $time;//访问时的时间戳
  323.                 //设置初始化参数
  324.                 private static function init($handler){
  325.                     self::$handler=$handler;
  326.                     self::$client_ip=!empty($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:"unKnown";//设置客户端的ip地址
  327.                     self::$lifetime=ini_get('session.gc_maxlifetime');//gc回收垃圾的最大生命周期
  328.                     self::$time=time();
  329.                 }
  330.                 //设置自定义的session处理方式,并开启session_start()
  331.                 public static function start(PDO $pdo){
  332.                     
  333.                     self::init($pdo);//设置当前使用的pdo句柄
  334.                     //__CLASS__:php起,返回类的名称
  335.                     session_set_save_handler(
  336.                         array(__CLASS__,'open'),
  337.                         array(__CLASS__,'close'),
  338.                         array(__CLASS__,'read'),
  339.                         array(__CLASS__,'write'),
  340.                         array(__CLASS__,'destroy'),
  341.                         array(__CLASS__,'gc')
  342.                     
  343.                     );
  344.                     //开启session
  345.                     session_start();
  346.                 }
  347.                 //open处理方法,不进行任何操作,返回true
  348.                 public static function open($session_path,$session_name){
  349.                     return true;
  350.                 }
  351.                 //close处理方法,不进行任何操作,返回true
  352.                 public static function close(){
  353.                     return true;
  354.                 }
  355.                 //读取session数据的操作
  356.                 public static function read($session_id){
  357.                     $sql='select update_time,client_ip,data from session where PHPSSESID="'.$session_id.'"';
  358.                 
  359.                     $stmt=self::$handler->prepare($sql);
  360.                     $stmt->execute(array($session_id));
  361.                     $result=$stmt->fetch(PDO::FETCH_ASSOC);
  362.                     //没有查询结果返回:''
  363.                     if(!$result){
  364.                         self::destroy($session_id);
  365.                         return "";
  366.                     }
  367.                     //ip地址有误返回:''
  368.                     if($result['client_ip'] != self::$client_ip){
  369.                         self::destroy($session_id);
  370.                         return '';
  371.                     }
  372.                     
  373.                     //数据合法返回数据
  374.                     return $result['data'];
  375.                 }
  376.                 //写入数据库
  377.                 public static function write($session_id,$session_data){
  378.                     
  379.                     $sql_select='select PHPSSESID,update_time,client_ip,data from session where PHPSSESID="'.$session_id.'"';
  380.                     $stmt=self::$handler->prepare($sql_select);
  381.                     $stmt->execute();
  382.                 
  383.                     //数据已经存在记录则更新
  384.                     if($result=$stmt->fetch(PDO::FETCH_ASSOC)){
  385.                         
  386.                         if($result['data'] != $session_data || self::$time > ($result['update_time']+10)){
  387.                             $sql_update='update sessoin set update_time=?,data=? where PHPSSESID="'.$session_id.'"';
  388.                             
  389.                             $stmt_update=self::$handler->prepare($sql_update);
  390.                             if($stmt_update->execute(array(self::$time,$session_data))){
  391.                                 return true;
  392.                             }
  393.                         }
  394.                     }else{
  395.                         
  396.                         //数据不存在记录则插入记录
  397.                         if(!empty($session_data)){
  398.                             $sql_insert='insert into session(PHPSSESID,update_time,client_ip,data) values(?,?,?,?)';
  399.                             $stmt_insert=self::$handler->prepare($sql_insert);
  400.                             if($stmt_insert->execute(array($session_id,self::$time,self::$client_ip,$session_data))){
  401.                                 return true;
  402.                             }
  403.                         }
  404.                     
  405.                     }
  406.                 }
  407.                 //调用该方法删除指定的session信息
  408.                 public static function destroy($session_id){
  409.                     $sql='delete from session where PHPSSESID="'.$session_id.'"';
  410.                     $stmt=self::$handler->prepare($sql);
  411.                     if($stmt->execute(array($session_id))){
  412.                         return true;
  413.                     }
  414.                 }
  415.                 //超过最大生命周期的时候删除数据
  416.                  static function gc($session_gc_maxlifetime){
  417.                      $sql="delete from session where update_time <?";
  418.                     
  419.                     $stmt=self::$handler->prepare($sql);
  420.                     $stmt->execute(array(self::$time-$session_gc_maxlifetime));
  421.                 
  422.                     return true;
  423.                 
  424.                 }
  425.             }
  426.             try{
  427.                 $pdo=new PDO('mysql:host=localhost;dbname=demo;charset=utf8','root','123456');
  428.             }catch(PDOException $e){
  429.                 echo $e->getMessage();
  430.             }
  431.             Session::start($pdo);
  432.             
  433.         ?>
  434.     12 session保存在memcache
  435.         
  436.     
  437.                 <?php
  438.             class MemSession {
  439.                 private static $handler=null;
  440.                 private static $lifetime=null;
  441.                 private static $time = null;
  442.                 const NS='session_';
  443.                 
  444.                 private static function init($handler){
  445.                     self::$handler=$handler;
  446.                     self::$lifetime=ini_get('session.gc_maxlifetime');
  447.                     self::$time=time();
  448.                 }
  449.                 public static function start(Memcache $memcache){
  450.                     self::init($memcache);
  451.                     session_set_save_handler(
  452.                             array(__CLASS__, 'open'),
  453.                             array(__CLASS__, 'close'),
  454.                             array(__CLASS__, 'read'),
  455.                             array(__CLASS__, 'write'),
  456.                             array(__CLASS__, 'destroy'),
  457.                             array(__CLASS__, 'gc')
  458.                         );
  459.                     session_start();
  460.                 }
  461.             
  462.                 public static function open($path, $name){
  463.                     return true;
  464.                 }
  465.                 public static function close(){
  466.                     return true;
  467.                 }
  468.                 public static function read($PHPSESSID){
  469.                     $out=self::$handler->get(self::session_key($PHPSESSID));
  470.                     if($out===false || $out == null)
  471.                         return '';
  472.                     return $out;
  473.                 }
  474.                 public static function write($PHPSESSID, $data){
  475.                     
  476.                     $method=$data ? 'set' : 'replace';
  477.                     return self::$handler->$method(self::session_key($PHPSESSID), $data, MEMCACHE_COMPRESSED, self::$lifetime);
  478.                 }
  479.                 public static function destroy($PHPSESSID){
  480.                     return self::$handler->delete(self::session_key($PHPSESSID));
  481.                 }
  482.                 public static function gc($lifetime){
  483.                     return true;
  484.                 }
  485.                 private static function session_key($PHPSESSID){
  486.                     $session_key=self::NS.$PHPSESSID;
  487.                     return $session_key;
  488.                 }    
  489.             }
  490.             $memcache=new Memcache;
  491.             $memcache->connect("localhost", 11211) or die("could not connect!");
  492.             
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值