1062
本地使用,一切正常;后端项目和前端项目都部署到服务器,一切正常;后端项目部署到服务器,并设置允许跨域访问后,本地前端项目使用服务器上后端项目接口时,问题来了:首先,使用postman测试获取图片验证码接口和验证图片验证码接口,正常。然后,在html中使用获取图片验证码接口,正常;最后,在JS中使用验证图片验证码接口,出错!!!分析通过问题描述,我们看出,问题出现在跨域上。那么,有两种可能,一种是因为跨域设置不正确;一种是因为thinkphp本身的问题。采用另外一种跨域配置,问题依然存在。那就是thinkphp本身的问题了,经查找资料,问题定位在thinkphp的session跨域上。跨子域解决办法其实不管是ThinkPHP还是php本身,在解决session跨域问题的时候都需要设置session.cookie_domain。针对session跨域这一问题的解决方法主要有以下几种:第一种情况:如果目录下没有.htaccess这个文件,也就是没有采取url伪静态的话,那么,在conf/config.php的第一行加上:1ini_set('session.cookie_domain',".domain.com");//跨域访问Session这时如果你开启了调试,那么可以用!但关闭了调试,就不管用了!第二种情况:如果你目录下有.htaccess这个文件,那么你在根目录,index.php的第一行加入:123<?php ini_set('session.cookie_domain',".domain.com");//跨域访问Session// 应用入口文件?>这种方法不管开不开启调试都管用!然而,我们的问题并不是跨子域的问题,而是完全跨域,所以上述方法无效。完全跨域解决办法获取图片验证码请求查看获取图片验证码的请求信息,Request Headers为:12345678Accept:image/webp,image/*,*/*;q=0.8Accept-Encoding:gzip, deflate, sdchAccept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4Connection:keep-aliveCookie:pma_lang=zh_CN; pma_collation_connection=utf8_unicode_ci; pma_iv-1=wnpO4gv0eQRW1AMHmGr2ww%3D%3D; pmaUser-1=weZPqS0%2BW7nzFUVHRdqcfA%3D%3DHost:api.voidking.comReferer:http://localhost/ajax/ajax.htmlUser-Agent:Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36Response Headers为:1234567891011Access-Control-Allow-Origin:*Cache-Control:post-check=0, pre-check=0Cache-Control:private, max-age=0, no-store, no-cache, must-revalidateConnection:keep-aliveContent-Type:image/pngDate:Sun, 27 Nov 2016 12:10:44 GMTExpires:Thu, 19 Nov 1981 08:52:00 GMTPragma:no-cacheServer:nginxSet-Cookie:PHPSESSID=721t4sqanvsii550m1dk8gq1o3; path=/; domain=.voidking.comTransfer-Encoding:chunked验证验证码请求查看验证验证码的请求信息,Request Headers为:12345678910Accept:application/json, text/javascript, */*; q=0.01Accept-Encoding:gzip, deflateAccept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4Connection:keep-aliveContent-Length:9Content-Type:application/x-www-form-urlencoded; charset=UTF-8Host:api.voidking.comOrigin:http://localhostReferer:http://localhost/ajax/ajax.htmlUser-Agent:Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36Response Headers为:123456789101112Access-Control-Allow-Origin:*Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0Connection:keep-aliveContent-Encoding:gzipContent-Type:text/html; charset=UTF-8Date:Sun, 27 Nov 2016 12:13:21 GMTExpires:Thu, 19 Nov 1981 08:52:00 GMTPragma:no-cacheServer:nginxSet-Cookie:PHPSESSID=149t0hhs2icqaaemvp39onkgp4; path=/; domain=.voidking.comTransfer-Encoding:chunkedVary:Accept-Encoding再次获取图片验证码请求Request Headers为:123456789Accept:image/webp,image/*,*/*;q=0.8Accept-Encoding:gzip, deflate, sdchAccept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4Cache-Control:max-age=0Connection:keep-aliveCookie:pma_lang=zh_CN; pma_collation_connection=utf8_unicode_ci; pma_iv-1=wnpO4gv0eQRW1AMHmGr2ww%3D%3D; pmaUser-1=weZPqS0%2BW7nzFUVHRdqcfA%3D%3D; PHPSESSID=721t4sqanvsii550m1dk8gq1o3Host:api.voidking.comReferer:http://localhost/ajax/ajax.htmlUser-Agent:Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36Response Headers为:12345678910Access-Control-Allow-Origin:*Cache-Control:private, max-age=0, no-store, no-cache, must-revalidateCache-Control:post-check=0, pre-check=0Connection:keep-aliveContent-Type:image/pngDate:Sun, 27 Nov 2016 13:26:21 GMTExpires:Thu, 19 Nov 1981 08:52:00 GMTPragma:no-cacheServer:nginxTransfer-Encoding:chunked三次请求比较第一次获取图片验证码请求,Cookie中没有PHPSESSID,所以,返回信息中有Set-Cookie。第二次获取图片验证码请求,Cookie中含有PHPSESSID,所以,返回信息中没有了Set-Cookie。而且第一次请求返回信息Set-Cookie中的PHPSESSID,和第二次请求请求信息Cookie中的PHPSESSID是相同的。而验证图片验证码的ajax请求,没有Cookie,自然也没有PHPSESSID,所以,返回信息中也有Set-Cookie。可见,我们需要在前端做一些修改,使之发送请求时带着Cookie。前端jquery设置1234567891011121314151617181920212223242526272829303132333435363738<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>jquery</title></head><body> <p> <img src="http://api.voidking.com/owner-bd/index.php/Home/CheckCode/getPicCode" alt=""> <input type="text" id="picCode"> <input type="button" id="send" value="验证"> </p><script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script><script> $(function(){ $('#send').click(function(){ //console.log(document.cookie); $.ajax({ url: 'http://api.voidking.com/owner-bd/index.php/Home/CheckCode/checkPicCode', type: 'POST', crossDomain: true, xhrFields: { withCredentials: true }, dataType: 'json', data: {code: $('#picCode').val()}, success: function(data){ console.log(data); }, error: function(xhr){ console.log(xhr); } }); }); });</script></body></html>请求时报错如下:1A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.出现了跨域报错,可见后端也需要做一些修改,使之可以接收跨域Cookie。后端nginx设置12add_header Access-Control-Allow-Origin http://localhost;add_header Access-Control-Allow-Credentials true;注意:服务器端Access-Control-Allow-Credentials参数为true时,Access-Control-Allow-Origin参数的值不能为*。后端nginx设置后,jquery的ajax请求正常了,可以携带Cookie,后端正常接收数据并返回数据。由于angular的ajax请求不同于jquery,所以,我们还需要研究一下angular怎么发送携带Cookie的跨域请求。前端angular设置1234567891011121314151617181920212223242526272829303132333435363738<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>angular</title> <script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script></head><body ng-app="myApp" > <p ng-controller="myCtrl"> <img src="http://api.voidking.com/owner-bd/index.php/Home/CheckCode/getPicCode" alt=""> <input type="text" id="picCode" ng-model="picCode"> <input type="button" ng-click="send()" value="验证"> </p><script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope, $http, $httpParamSerializer) { $scope.send = function(){ $http({ method:'POST', url:'http://api.voidking.com/owner-bd/index.php/Home/CheckCode/checkPicCode', headers:{ 'Content-Type':'application/x-www-form-urlencoded' }, withCredentials: true, dataType: 'json', data: $httpParamSerializer({code: $scope.picCode}) }).then(function successCallback(response) { console.log(response.data); $scope.username = response.data.username; }, function errorCallback(response) { console.log(response.data); }); } });</script> </body></html>推荐教程:《TP5》以上就是thinkphp中session跨域问题解决的详细内容
0
0 1424天前
1032
thinkphp 日志记录日志的处理工作是由系统自动进行的,在开启日志记录的情况下,会记录下允许的日志级别的所有日志信息。其中,为了性能考虑,SQL日志级别必须在调试模式开启下有效,否则就不会记录。 系统的日志记录由核心的Think\Log类及其驱动完成,提供了多种方式记录了不同的级别的日志信息。默认情况下只是在调试模式记录日志,要在部署模式开启日志记录,必须在配置中开启LOG_RECORD参数,以及可以在应用配置文件中配置需要记录的日志级别,例如:'LOG_RECORD' => true, // 开启日志记录'LOG_LEVEL' =>'EMERG,ALERT,CRIT,ERR', // 只记录EMERG ALERT CRIT ERR 错误日志级别ThinkPHP对系统的日志按照级别来分类,包括:EMERG 严重错误,导致系统崩溃无法使用ALERT 警戒性错误, 必须被立即修改的错误CRIT 临界值错误, 超过临界值的错误ERR 一般性错误WARN 警告性错误, 需要发出警告的错误NOTICE 通知,程序可以运行但是还不够完美的错误INFO 信息,程序输出信息DEBUG 调试,用于调试信息SQL SQL语句,该级别只在调试模式开启时有效记录方式日志的记录方式默认是文件方式,可以通过驱动的方式来扩展支持更多的记录方式。记录方式由LOG_TYPE参数配置,例如:'LOG_TYPE' => 'File', // 日志记录类型 默认为文件方式File方式记录,对应的驱动文件位于系统的Library/Think/Log/Driver/File.class.php。手动记录一般情况下,系统的日志记录是自动的,无需手动记录,但是某些时候也需要手动记录日志信息,Log类提供了3个方法用于记录日志。方法描述Log::record()记录日志信息到内存Log::save()把保存在内存中的日志信息(用指定的记录方式)写入Log::write()实时写入一条日志信息由于系统在请求结束后会自动调用Log::save方法,所以通常,你只需要调用Log::record记录日志信息即可。record方法用法如下:\Think\Log::record('测试日志信息');默认的话记录的日志级别是ERR,也可以指定日志级别:\Think\Log::record('测试日志信息,这是警告级别','WARN');record方法只会记录当前配置允许记录的日志级别的信息,如果应用配置为:'LOG_LEVEL' =>'EMERG,ALERT,CRIT,ERR', // 只记录EMERG ALERT CRIT ERR 错误那么上面的record方法记录的日志信息会被直接过滤,或者你可以强制记录:\Think\Log::record('测试日志信息,这是警告级别','WARN',true);采用record方法记录的日志信息不是实时保存的,如果需要实时记录的话,可以采用write方法,例如:\Think\Log::write('测试日志信息,这是警告级别,并且实时写入','WARN');write方法写入日志的时候 不受配置的允许日志级别影响,可以实时写入任意级别的日志信息。推荐教程:《TP5》以上就是thinkphp日志记录配置教程的详细内容
0
0 1424天前
1124
thinkphp5的Redis缓存配置thinkphp采用cache类提供缓存功能支持,采用驱动方式,在使用缓存之前需要进行初始化操作。支持的缓存类型包括file、memcache、wincache、sqlite、redis和xcache等,默认情况下是file类型,配置redis缓存可以单一配置redis也可以同时使用多个缓存类型。配置方式分别如下:thinkphp采用cache类提供缓存功能支持,采用驱动方式,在使用缓存之前需要进行初始化操作。支持的缓存类型包括file、memcache、wincache、sqlite、redis和xcache等,默认情况下是file类型,配置redis缓存可以单一配置redis也可以同时使用多个缓存类型。配置方式分别如下:一、仅配置redis缓存,在配置文件(app/config.php)中修改缓存设置如下:二、配置多个缓存类型,使用符合缓存类型,配置方式如下:12345678910111213141516171819202122232425'cache' => [ // 使用复合缓存类型 'type' => 'complex', // 默认使用的缓存 'default' => [ // 驱动方式 'type' => 'File', // 缓存保存目录 'path' => CACHE_PATH, ], // 文件缓存 'file' => [ // 驱动方式 'type' => 'file', // 设置不同的缓存保存目录 'path' => RUNTIME_PATH . 'file/', ], // redis缓存 'redis' => [ // 驱动方式 'type' => 'redis', // 服务器地址 'host' => '192.168.1.100', ], ],使用符合缓存类型时,需要根据需要使用store方法切换缓存。当使用Cache::set('name', 'value');Cache::get('name');的时候,使用的是default缓存标识的缓存配置。如果需要切换到其它的缓存标识操作,可以使用:// 切换到file操作Cache::store('file')->set('name','value');Cache::get('name');// 切换到redis操作Cache::store('redis')->set('name','value');Cache::get('name');比如,查询一篇文章时首先从redis中查询,若未查到信息则从数据库中查询出结果,并存储到redis中。推荐教程:《TP5》以上就是thinkphp5的Redis缓存配置的详细内容
0
0 1424天前
1244
出现乱码的问题是因为thinkphp分页类中的,构造url时存在的问题,thinkphp的分页url是使用"/"来分隔参数的,在将数据传递到url中时,经过url加密,第二次传递的时候就会乱码了,而如果我们使用"?"和"&"来分隔参数的话,就不会出现这个问题了。所以要修改的内容是thinkphp的分页类文件:/ThinkPHP/Extend/Library/ORG/Util/Page.class.php文件。具体修改的代码是:1、在thinkphp分页类文件Page.class.php的最后加上一个自定义函数,用于替换url中的参数分隔符号,函数内容如下:1234567private function clin_page_url($parameter){ $url = U(''); $url = str_replace('.html', '?', $url); foreach ($parameter as $key => $value) { $url .= $key.'='.$value.'&'; } $url = substr($url, 0,-1); return $url;}自学php博客2、修改最终生成的url在Page.class.php文件的第99行,将原来的1$url=U('',$parameter);修改为:1$url=$this->clin_page_url($parameter); // 生成标准的url经过这两步修改就可以解决thinkphp分页乱码的问题了。相关参考:thinkphp教程以上就是如何解决thinkphp分页出现乱码问题的详细内容
0
0 1424天前
1168
下面由thinkphp框架开发栏目给大家介绍Thinkphp volist多重循环原样输出数组key值的使用总结,希望对需要的朋友有所帮助!最近因为项目的缘故,要使用到volist。在这个过程中,遇到了一些小问题,主要就是volist在循环输出多重数据的时候,如何输出key。网上查阅了不少资料,很失望的是,大多资料就是粘贴复制Thinkphp手册上volist标签的说明。为了帮助其他人,故决定写下这篇文章。( 在这里,使用的框架是Thinkphp3.2,其它的相关知识,是php数组)。首先贴出控制器里面代码:123456public function check(){ $multiArr = [['a' => ['num' => '1',], 'b' => ['num' => '2',]], ['c' => ['num' => '3',], 'd' => ['num' => '4',]]]; $this->assign('list', $multiArr); $this->display();}打印出来的格式如下:12345678910111213141516171819202122232425Array( [0] => Array ( [a] => Array ( [num] => 1 ) [b] => Array ( [num] => 2 ) ) [1] => Array ( [c] => Array ( [num] => 3 ) [d] => Array ( [num] => 4 ) ))很明显,这是一个多重数组。如果想得到他们的key值,如果使用volist,代码如下:12345678910111213<tr><volist name="list" id="data" key="k"><td>{$k}</td><td><tr><volist name="data" id="vo"><td>{$key}</td><td>{$vo.num}</td></volist></tr></td></volist></tr>得到的结果如下:12341a 1 b 22c 3 d 4在这里,很明显,外重的循环的key值是系统默认的,而里面的这一重循环出来的key值是由数据本身决定的而不是由循环控制的。1http://document.thinkphp.cn/manual_3_2.html#volist在Thinkphp手册里面,这个说的很清楚。如果到这里,没其他的要求的话,其实可以满足大多数输出key值的要求了。但是如果数组改成下面的格式:123456789101112131415161718$multiArr = [ 'aaa' => [ 'a' => [ 'num' => '1', ], 'b' => [ 'num' => '2', ] ], 'bbb' => [ 'c' => [ 'num' => '3', ], 'd' => [ 'num' => '4', ] ] ];并且此时,外重循环出的key值和内层循环出的key值均由数据本身决定,而不是循环控制的,那该怎么处理呢?好吧,当时走入误区了,一直想用两个volist进行循环,然后输出key值(它由数据本身决定),但是尝试了好久,发现还是不行。查阅了不少的资料,发现好多都没有讲到这个问题。谋杀了无数脑细胞,看着代码,突然想到,foreach也可以进行这种循环操作,为啥不尝试用这个标签呢?或者把这两个标签结合起来使用呢?顿时,豁然开朗。于是,把前端的代码改成如下:12345678910111213<tr> <foreach name="list" item="data" key="i"> <td>{$i}</td> <td> <tr> <volist name="data" id="vo" key="k"> <td>{$key}</td> <td>{$vo.num}</td> </volist> </tr> </td> </foreach> </tr>得到的结果如下:1234aaaa 1 b 2bbbc 3 d 4满足了上面的要求。总结如下:在thinkphp中,用volist标签进行多重数组循环输出的时候,若想输出由数据控制的key值,而不是默认的,可以把foreach标签和volist标签结合起来使用,就能原样输出key值了。以上就是Thinkphp volist多重循环原样输出数组key值的详细内容
0
0 1424天前
1100
【一】概论(1)介绍Highcharts基于jquery开发的国外图标插件,统计图,折线图,饼状图等常常用到。国内也有一款类似插件echarts,由百度开发。(2)支持特效demo:3D、仪表盘、折现、类心电图实时刷新、柱状、点状、雷达、漏斗、金字塔漏斗图:常用于销售走势,最上方为有意向用户,底部为成交客户。具体有以下几类(3)应用实例:QQ的全国在线人数分布,通过Flash做的;百度echarts的全国数据分布,通过js做的非常直观反映出中国互联网发展情况和地域。亮点越多说明当地互联网越发达。发达地区有北上广,重庆(4)echarts包含更加丰富的demo,拓展了许多,包含全球航线、股票数据走势(5)用法基本一致【二】案例使用Highcharts实现部门人数统计要求:使用图标形式统计出每个部门人数(1)准备和步骤:1. 选样式目录,这里我用的examples/column-rotated-labels;2. 分析demo:①引入jquery和js类文件;②替换data数据;③声明div图标容器,用来放置图标(2)开始编写1. 修改模板文件User/showList.html,将下面的统计按钮设置链接,点击后跳到统计页面这里不用做任何操作,所以直接修改a标签的href即可,写成什么呢?这要看方法了2. 定义图标页面方法charts,方法写在了User控制器里,所以href写为__CONTROLLER__/charts3. 定义charts方法展示图表模板文件1234//charts图表 public function charts(){ $this->display(); }4. 复制模板文件到指定位置;同时为了更快在线上访问网站,需要复制静态资源文件到站点目录下;①这里是复制到User/charts,html下;②引入静态资源并修改路径:这里为了方便,我直接把整个code复制到了静态资源目录下,后期使用的插件都放到plugin(插件)目录下5. 改写chars方法,查询出数据,替换模板文件中的数据先分析下最终数据格式:,产品部:10,技术部20,外交部30......仅仅一个数据表无法实现,所以需要联表查询(sp_user、sp_dept)主表sp_user(t1);从表sp_dept(t2);关联条件:t1.dept_id = t2.id原生SQL语句table方法:1select t2.name as deptname,count(*) as count from sp_user as t1,sp_dept as t2 where t1.dept_id=t2.id group by deptname;在Navicat中运行后输出正确,所以接下来TP连贯操作:1234567public function charts(){$model = M(); //连贯操作$data = $model->field('t2.name as deptname,count(*) as count')->table('sp_user as t1,sp_dept as t2') ->where('t1.dept_id=t2.id')->group('deptname')->select();dump($data);die;$this->display(); }输出$data结果:1234567891011121314array(3) { [0] => array(2) { ["deptname"] => string(9) "人力部" ["count"] => string(1) "3" } [1] => array(2) { ["deptname"] => string(9) "技术部" ["count"] => string(1) "2" } [2] => array(2) { ["deptname"] => string(9) "财务部" ["count"] => string(1) "3" }}如果当前使用的ThinkPHP版本为5.6+,则可以直接将data二维数组assign,不需要任何处理。5.6以下版本需要进行字符串拼接1234567$str = "[";//循环遍历字符串 foreach ($data as $key => $value) { $str .= "['".$value['deptname']."',".$value['count']."],"; } //去除最后的, $str = rtrim($str,','); $str .= "]";6. 变量传递给模板;7. 修改模板,接收变量。删除原先的数组,改为传递变量即可data:{$str},(3)细节完善1. 修改表头2. 修改左侧单位信息3. 修改鼠标悬浮效果(截止当前)4. 修改图标上小数点(1f改为0f,表示精确到0位);5. 至于打印图片的操作,需要修改highcharts.js,从源码上修改即可。查询输入相关单词,修改即可总结:(1).1f表示精确到1位小数(如3.0、5.0),若不想要.0,则可以精确到0位小数即可(如3、5)以上就是ThinkPHP---插件highcharts的全部内容。相关参考:thinkphp教程以上就是插件highcharts在thinkphp中的使用的详细内容
0
0 1424天前
1184
一、登录所用到组件1、视图模板:安装:composer require topthink/think-view2、验证码:安装:composer require topthink/think-captcha3、session:需要开启session:打开app下的middeware.php文件,内部有个全局中间件 ,最后一行去掉注释即可。准备基本完毕,手动开启教程。二、前台搭建(layui框架)2.1、你得先获取layui,去layui官网下载或者百度搜一下layui 的cdn2.2、引入,我是放在tp6>public>static文件夹下。如图2-1.图2-1 layui所在文件夹图2.3:登录界面:界面图如2-2;图2-2:登录界面图代码如下所示:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/layui/css/layui.css"></head><body><div class="layui-container"> <div class="layui-row"> <div class="layui-col-md4 layui-col-md-offset4" style="margin-top: 100px; box-shadow: 2px 2px 5px #ccc"> <div style="height: 80px; text-align: center; font-size:30px; ">后台登录</div> <form class="layui-form layui-form-pane" action=""> <div class="layui-form-item" pane> <label class="layui-form-label">用户名</label> <div class="layui-input-block"> <input type="text" name="name" required lay-verify="required" placeholder="请输入标题" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">密码</label> <div class="layui-input-block"> <input type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item" pane> <label class="layui-form-label">验证码</label> <div class="layui-input-inline"> <input type="text" name="yzm" style="width:60%" required lay-verify="required" placeholder="请输入验证码" autocomplete="off" class="layui-input"> <div style="display: inline" class="layui-form-mid layui-word-aux"><img id='captcha' style="display: inline" src="{:captcha_src()}" alt="captcha" /></div> </div> </div> <div class="layui-form-item"> <div class="layui-input-block"> <input type="button" class="layui-btn" lay-submit lay-filter="formDemo" value="立即提交"></input> <button type="reset" class="layui-btn layui-btn-primary">重置</button> </div> </div> </form> </div> </div> <script src="/static/layui/layui.all.js"></script><script> //只需要引入layui.all.js就ok //这里我们需要用到form表单,jquery的ajax提交,layui的弹弹窗 //所以需要引用,下面数组就是引入的组件。 layui.use(['form', 'jquery', 'layer'], function(){ var form = layui.form; var $ = layui.jquery; //上两行就是引用form 和$ ,下面需要用到 //监听表单提交,获取表单信息:submit(formDemo)数据对应这个lay-filter="formDemo" form.on('submit(formDemo)', function(data){ //从表单中获取相应数据 var name = data.field.name; var password = data.field.password; var yzm = data.field.yzm; $.ajax({ url:"userLogin",//请求地址,当前在admin/user/userLogin下,提交给当前方法即可 data: {//发送给服务器的数据 'name':name, 'password':password, 'yzm':yzm }, type:"Post",//提交方式 dataType:"json", success:function(data){//成功回调 if(data.status==0){//登录失败,status后台自定义状态码 layer.msg(data.msg);//layer自带的弹窗,msg后台自定义消息, \\emm 就是最开始layui.use中引用的layer,不然这里没法使用。 }else{//登录成功 msg后台自定义消息 layer.msg(data.msg); //行吧,这里是自定义跳转,登录成功过后直接跳到主页 window.location.href = "{:url('admin/index/index')}" } return false; }, error:function(data){ console.log('==错误信息=='); return false; } }); return false; }); //提交数据结束 // 验证码刷新,,通过jquery获取图片dom,并实现点击功能。 $("#captcha").click(function(event){ // jqery中获取id是上面这样的,如果是获取class就是 $(".captcha") // 当然我这里不涉及类名。 console.log('我被点击了');控制台输出这鬼东西被点击了没有 console.log(event); //给当前图片的src换一个新的url,后面带上一个随机数。 //虽然我还不知道原理, //但是这样就能让验证码刷新, //请求tp6这个captcha_src()方法,如果不加后面那串估计后台认为 //什么也不给你请求个锤子,原来那个给你 this.src = "{:captcha_src()}?"+Math.random(); console.log(this.src);//我打印了一下值得变化,事实上只有后面随机数变了 }) });</script> </body></html>前台代码基本上是这样:验证码哪一行有毛病,我不想解决。三、后台逻辑实现。需要用到一张数据表:我这是admin表,包含了以下字段如图3-1图3-1 数据库设计表其实登录 不需要group_id last_login_time 等字段。这里我是有其他功能要实现。如果我开心过两天发张博客。我没用模型,你也可以用模型:这里我建立一个模型吧:admin模型如下:创建模型命令php think make:mode admin@UserModel我这里开启了多应用模式,admin是我的应用,如果你没有使用多应用模式,把admin@去掉,当然,你也可以手动创建哈。得到以下模型::图3-2图3-2 模型位置图:UserModel模型代码:123456789101112131415161718192021222324252627282930<?phpdeclare (strict_types = 1);namespace app\admin\model;use think\Model; class UserModel extends Model{ //绑定主键 protected $pk = 'id'; //绑定表 表名 protected $table='msg_admin'; //开启自动时间戳 protected $autoWriteTimestamp =true; // 设置字段信息。。虽然可以不用,但文档说可以减少一次查询,还是用吧 protected $schema = [ 'id' => 'int', 'name' => 'string', 'password' => 'string', 'status' => 'tinyint', 'group_id' => 'int', 'create_time' => 'datetime', 'update_time' => 'datetime', 'last_login_time' => 'datetime', ]; // 模型初始化 protected static function init() { //TODO:初始化内容 }}对:在这之前你去要配置一下ENV变量,能链接数据库::自己去配置吧。3-2:登录逻辑及代码::第一步:检查session是否存在用户,存在直接跳到后台,否则就执行下一步第二步:检查是不是post请求,如果是执行登录操作:不是渲染视图,将登录界面返回给用户;第三步:登录中:获取用户传入数据,检查是否为空,(验证数据:我没写验证,懒);根据用户用户名查找用户信息,匹配密码,写入session,完成登录代码如下:::1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677<?phpnamespace app\admin\controller;use app\BaseController;use think\facade\Db;use think\Request;use app\validate\UserValidate;use think\facade\View;use think\facade\session; class User extends BaseController{ protected $request; /** * 检查用户登录 * 有登录提交时,进入登录功能,没有登录请求返回页面 * 获取用户信息 校验 查询数据库 * @param Request $request * @return string|\think\response\Json * @throws \Exception */ public function userLogin(Request $request){ if(!empty(session('adminAccount')) ){ //如果用户已经登录,跳转到后台首页 return redirect((string)url('index/index')); } if($request->isPost()){ $name= $request->param('name'); $password = $request->param('password'); $yzm = $request->param('yzm'); //判断是否没有数据 if(empty($name)&&empty($password)||empty($yzm)){ return json(['status'=>0,'msg'=>'未提交数据']); } //数据不为空,查询用户是否存在 $adminInfo = Db::name('msg_admin')->where('name','=',$name)->find(); //halt($adminInfo); if(!empty($adminInfo) && $adminInfo['status']!=1){ return json(['statsu'=>0,'msg'=>'用户不存在']); } if(!captcha_check($yzm)){ return json(['status'=>0,'msg'=>'验证码不正确']); } //md5加密密码::password_salt是一个自定义密码加密具体 //具体是在common.php中实现,具体如下::: /** <?php // 应用公共文件 //通用密码加密 function password_salt($str){ $salt='sttr'; return md5($str.$salt); } */ // if($adminInfo['password']!=password_salt($password)){ //这里数据库信息是手动添加,所以没有使用加密。 if($adminInfo['password']!=$password){ return json(['status'=>0,'msg'=>'密码不正确']); } //将用户存入session中 session('adminAccount',$adminInfo); return json(['status'=>1,'msg'=>'登录成功']); }else{ return View::fetch(); } } //退出登录 public function loginOut(){ session::clear(); //重定向到登录界面》》》》 return redirect('userLogin'); }}这就是登录逻辑了:::这里我还有一个问题:就是进入后台首页后,通过tp51,tp5方法,通过模板语法无法获取session,不知小伙伴们有没有解决方法,有的话告诉我一声。谢谢。我的解决办法是:在首页index.html和index控制器中:index控制器中:::123456789101112<?phpdeclare (strict_types = 1);namespace app\admin\controller;use think\facade\View;class Index{ public function index() { View::assign('user',session('adminAccount')); return View::fetch(); }}我将他送个session的值给了user,前台从user中取出::T_T前台代码::123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/layui/css/layui.css"></head><body><div class="layui-layout layui-layout-admin"> <div class="layui-header"> <div class="layui-logo">XXX后台管理系统</div> <!-- 头部区域(可配合layui已有的水平导航) --> <ul class="layui-nav layui-layout-left"> <li class="layui-nav-item"><a href="">主页</a></li> <li class="layui-nav-item"><a href="">商品管理</a></li> <li class="layui-nav-item"><a href="">用户管理</a></li> <li class="layui-nav-item"> <a href="javascript:;">其它</a> <dl class="layui-nav-child"> <dd><a href="">邮件管理</a></dd> <dd><a href="">消息管理</a></dd> <dd><a href="">授权管理</a></dd> </dl> </li> </ul> <ul class="layui-nav layui-layout-right"> <li class="layui-nav-item"> <a href="javascript:;"> <img src="" class="layui-nav-img"> {$user.name} <!-- 具体看这里,取出session的值::::: --> </a> <dl class="layui-nav-child"> <dd><a href="">个人资料</a></dd> <dd><a href="">安全设置</a></dd> </dl> </li> <li class="layui-nav-item"><a href="{:url('user/loginOut')}">安全退出</a></li> </ul> </div> <div class="layui-side layui-bg-black"> <div class="layui-side-scroll"> <!-- 左侧导航区域(可配合layui已有的垂直导航) --> <ul class="layui-nav layui-nav-tree" lay-filter="test"> <li class="layui-nav-item layui-nav-itemed"> <a class="" href="javascript:;">商品管理</a> <dl class="layui-nav-child"> <dd><a href="javascript:;">商品列表</a></dd> <dd><a href="javascript:;">添加商品</a></dd> </dl> </li> <li class="layui-nav-item"> <a href="javascript:;">订单管理</a> <dl class="layui-nav-child"> <dd><a href="javascript:;">订单列表</a></dd> <dd><a href="javascript:;">待审核</a></dd> <dd><a href="javascript:;">配送中</a></dd> <dd><a href="javascript:;">完成订单</a></dd> </dl> </li> <li class="layui-nav-item"><a href="">其他功能</a></li> </ul> </div> </div> <div class="layui-body"> <!-- 内容主体区域 --> </div> <div class="layui-footer"> <!-- 底部固定区域 --> © layui.com - 底部固定区域 </div></div><script src="/static/layui/lay/modules/jquery.js"></script><script src="/static/layui/layui.all.js"></script><script> //JavaScript代码区域 layui.use('element', function(){ var element = layui.element; });</script></body></html>后台主页界面图3-3图3-3 后台主页界面图具体内容就这样,有问题呢百度,还是有问题还是百度。以上就是Thinkphp6 + layui 实现后台登录(验证码刷新)的详细内容
0
0 1424天前
1400
基于Thinkphp3.2的QQ第三方认证登录扩展类基于Thinkphp3.2的qq第三方认证登录扩展类,其实以下类也是我从TP官网收集整理得来的,稍微做了一下修改和完善。这里我将文件放存在“/Application/Common/Lib/Qqconnect.class.php”。(其实这个文件路径根据自己喜好来放)实例化1$Qqconnect = new \Common\Lib\Qqconnect();在__construct方法中你可以直接写你的app_id、app_key和回调地址也可以根据自己的喜好,改一下代码传参或者写到配置文件。调用方法:1. 在qq的登录按钮的方法中调用getAuthCode方法12$qqobj=new \Org\Util\Qqconnect();$qqobj->getAuthCode();2.在回调地址的方法中调用getUsrInfo方法12$qqobj=new \Org\Util\Qqconnect();$result=$qqobj->getUsrInfo();3.getAuthCode方法中的参数scope根据自身需要添加值get_user_info,list_album,upload_pic,do_like。Qqconnect.class.php123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183<?php// +----------------------------------------------------------------------// | Copyright (c) 2015.// +----------------------------------------------------------------------// | Author: qiandutianxia <852997402@qq.com>// +----------------------------------------------------------------------namespace Common\Lib;/** * qq第三方登录认证 */class Qqconnect { private static $data; //APP ID private $app_id=""; //APP KEY private $app_key=""; //回调地址 private $callBackUrl=""; //Authorization Code private $code=""; //access Token private $accessToken=""; private $openid=""; public function __construct(){ $this->app_id=""; $this->app_key=""; $this->callBackUrl=""; //你的回调地址 //检查用户数据 if(empty($_SESSION['QC_userData'])){ self::$data = array(); }else{ self::$data = $_SESSION['QC_userData']; } } //获取Authorization Code public function getAuthCode(){ $url="https://graph.qq.com/oauth2.0/authorize"; $param['response_type']="code"; $param['client_id']=$this->app_id; $param['redirect_uri']=$this->callBackUrl; //生成唯一随机串防CSRF攻击 $state = md5(uniqid(rand(), TRUE)); $_SESSION['state']=$state; $param['state']=$state; $param['scope']="get_user_info"; $param =http_build_query($param,'','&'); $url=$url."?".$param; header("Location:".$url); } //通过Authorization Code获取Access Token private function _getAccessToken(){ $this->code=$_GET['code']; $url="https://graph.qq.com/oauth2.0/token"; $param['grant_type']="authorization_code"; $param['client_id']=$this->app_id; $param['client_secret']=$this->app_key; $param['code']=$this->code; $param['redirect_uri']=$this->callBackUrl; $param =http_build_query($param,'','&'); $url=$url."?".$param; return $this->getUrl($url); } //获取openid public function _setOpenID(){ $rzt=$this->_getAccessToken(); parse_str($rzt,$data); $this->accessToken=$data['access_token']; $url="https://graph.qq.com/oauth2.0/me"; $param['access_token']=$this->accessToken; $param =http_build_query($param,'','&'); $url=$url."?".$param; $response=$this->getUrl($url); //--------检测错误是否发生 if(strpos($response, "callback") !== false){ $lpos = strpos($response, "("); $rpos = strrpos($response, ")"); $response = substr($response, $lpos + 1, $rpos - $lpos -1); } $user = json_decode($response); if(isset($user->error)){ exit("错误代码:100007"); } return $user->openid; } //获取信息 public function getUserInfo(){ if($_GET['state'] != $_SESSION['state']){ exit("错误代码:300001"); } $openid=$this->_setOpenID(); if(empty($openid)){ return false; } session('openid',$openid); $url="https://graph.qq.com/user/get_user_info"; $param['access_token']=$this->accessToken; $param['oauth_consumer_key']=$this->app_id; $param['openid']=$openid; $param =http_build_query($param,'','&'); $url=$url."?".$param; $rzt=$this->getUrl($url); return $rzt; } public function getOpenId(){ if($_GET['state'] != $_SESSION['state']){ exit("错误代码:300001"); } $rzt=$this->_getAccessToken(); parse_str($rzt,$data); $this->accessToken=$data['access_token']; $url="https://graph.qq.com/oauth2.0/me"; $param['access_token']=$this->accessToken; $param =http_build_query($param,'','&'); $url=$url."?".$param; $response=$this->getUrl($url); //--------检测错误是否发生 if(strpos($response, "callback") !== false){ $lpos = strpos($response, "("); $rpos = strrpos($response, ")"); $response = substr($response, $lpos + 1, $rpos - $lpos -1); } $info = object_array(json_decode($response)); $qq['access_token'] = $this->accessToken; $qq['openid'] = $info['openid']; session('qq',$qq); return $info['openid']; } public function getInfo($openid='',$accessToken=''){ $url="https://graph.qq.com/user/get_user_info"; $param['oauth_consumer_key']=$this->app_id; $param['access_token']=$accessToken; $param['openid']=$openid; $param =http_build_query($param,'','&'); $url=$url."?".$param; $rzt=$this->getUrl($url); $info = object_array(json_decode($rzt)); return $info; } //CURL GET private function getUrl($url){ $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 5); if (!empty($options)){ curl_setopt_array($ch, $options); } $data = curl_exec($ch); curl_close($ch); return $data; } //CURL POST private function postUrl($url,$post_data){ $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); ob_start(); curl_exec($ch); $result = ob_get_contents(); ob_end_clean(); return $result; }}下面是控制器中的代码LoginController.class.php该文件主要包含两个方式点击QQ登陆的时候访问的地址1234public function qq_login(){ $Qqconnect = new \Common\Lib\Qqconnect(); $Qqconnect->getAuthCode(); }回调访问地址123456789101112131415161718192021public function callback(){ $Qqconnect = new \Common\Lib\Qqconnect(); $openid = $Qqconnect->getOpenId(); $qq = session('qq'); $Member = M('Member'); $map = array(); $map['openid'] = $openid; $userInfo = $Member->where($map)->find(); if(!empty($userInfo)){ $this->success('登陆成功!',U('Member/index')); }else{ $Qqconnect = new \Common\Lib\Qqconnect(); $userInfo = $Qqconnect->getInfo($qq['openid'],$qq['access_token']); print_r($userInfo); exit; }以上只是简单的示例,大家可以参考一下再进行修改和完善。如有不明白的地方可以留言讨论。推荐教程:《PHP视频教程》以上就是以Thinkphp3.2为基础的QQ第三方认证登录扩展类的详细内容
0
0 1424天前
983
Thinkphp 框架扩展之类库扩展操作详解这篇文章主要介绍了Thinkphp 框架扩展之类库扩展操作,结合实例形式分析了Thinkphp 类库扩展的相关原理、实现方法与操作注意事项,需要的朋友可以参考下本文实例讲述了Thinkphp 框架扩展之类库扩展操作。分享给大家供大家参考,具体如下:库类扩展ThinkPHP的类库主要包括公共类库和应用类库,都是基于命名空间进行定义和扩展的。只要按照规范定义,都可以实现自动加载。公共库类公共类库通常是指ThinkPHP/Library目录下面的类库,例如:Think目录:系统核心类库Org目录:第三方公共类库这些目录下面的类库都可以自动加载,你只要把相应的类库放入目录中,然后添加或者修改命名空间定义。 你可以在Org/Util/目录下面添加一个Image.class.php 文件,然后添加命名空间如下:123namespace Org\Util;class Image {}这样,就可以用下面的方式直接实例化Image类了:1$image = new \Org\Util\Image;除了这些目录之外,你完全可以在ThinkPHP/Library目录下面添加自己的类库目录,例如,我们添加一个Com目录用于企业类库扩展:Com\Sina\App类(位于Com/Sina/App.class.php )123namespace Com\Sina;class App {}Com\Sina\Rank类(位于Com/Sina/Rank.class.php)123namespace Com\Sina;class Rank {}公共类库除了在系统的Library目录之外,还可以自定义其他的命名空间,我们只需要注册一个新的命名空间,在应用或者模块配置文件中添加下面的设置参数:123'AUTOLOAD_NAMESPACE' => array( 'Lib' => APP_PATH.'Lib',)我们在应用目录下面创建了一个Lib目录用于放置公共的Lib扩展,如果我们要把上面两个类库放到Lib\Sina目录下面,只需要调整为:Lib\Sina\App类(位于Lib/Sina/App.class.php )123namespace Lib\Sina;class App {}Lib\Sina\Rank类(位于Lib/Sina/Rank.class.php)123namespace Lib\Sina;class Rank {}如果你的类库没有采用命名空间的话,需要使用import方法先加载类库文件,然后再进行实例化,例如: 我们定义了一个Counter类(位于Com/Sina/Util/Counter.class.php):12class Counter {}在使用的时候,需要按下面方式调用:12import('Com.Sina.Util.Couter');$object = new \Counter();应用类库应用类库通常是在应用或者模块目录下面的类库,应用类库的命名空间一般就是模块的名称为根命名空间,例如: Home\Model\UserModel类(位于Application\Home\Model)namespace Home\Model;use Think\Model;class UserModel extends Model{}Common\Util\Pay类(位于Application\Common\Util)123namespace Common\Util;class Pay {}Admin\Api\UserApi类(位于Application\Admin\Api)1234namespace Admin\Api;use Think\Model;class UserApi extends Model{}记住一个原则,命名空间的路径和实际的文件路径对应的话 就可以实现直接实例化的时候自动加载。推荐教程:《PHP视频教程》以上就是Thinkphp 框架扩展之类库扩展操作解析的详细内容
0
0 1424天前