登录功能与及用token对uid的加密和管理员对数据的

编辑: admin 分类: 电脑知识 发布时间: 2023-06-14 来源:互联网
文件的展示:1.前台路由文件:index.js
  1. import { createRouter, createWebHistory } from 'vue-router'
  2. import Ad from '../views/kedaishu/ad.vue'
  3. import Index from '../views/Index.vue'
  4. import Login from '../views/Login.vue'
  5. import Course from '../views/kedaishu/course.vue'
  6. import AdminUser from '../views/admin/user.vue'
  7. const routes = [
  8. {
  9. path: '/', // 路由地址配置,就是浏览器上的url
  10. name: 'home', // 是页面的名称,自定义,但是不要重复
  11. component: Index, // 这个是页面文件的路径
  12. },
  13. {
  14. path: '/login',//创建登录页面的路由
  15. name: 'login',
  16. component: Login,
  17. },
  18. {
  19. path: '/admin_user', // 路由地址配置,就是浏览器上的url
  20. name: 'AdminUser', // 是页面的名称,自定义,但是不要重复
  21. component: AdminUser, // 这个是页面文件的路径
  22. },
  23. {
  24. path: '/ad', // 路由地址配置,就是浏览器上的url
  25. name: 'ad', // 是页面的名称,自定义,但是不要重复
  26. component: Ad, // 这个是页面文件的路径
  27. },
  28. {
  29. path: '/course', // 路由地址配置,就是浏览器上的url
  30. name: 'course', // 是页面的名称,自定义,但是不要重复
  31. component: Course, // 这个是页面文件的路径
  32. }
  33. ]
  34. const router = createRouter({
  35. history: createWebHistory(process.env.BASE_URL),
  36. routes
  37. })
  38. export default router
2.前台登录文件:Login.vue
  1. <template>
  2. <div class="container">
  3. <div style="text-align: center">
  4. <img src="@/assets/logo.png" alt="logo" />
  5. <h3>phpAdmin后台管理</h3>
  6. </div>
  7. <div class="main">
  8. <!-- label-width="auto" 导致ElementPlusError: [ElForm] unexpected width 0 -->
  9. <el-form :model="state" size="large">
  10. <el-form-item prop="account">
  11. <el-input v-model="state.account" name="account" class="w-50 m-2" placeholder="请输入账号">
  12. <template #prefix>
  13. <el-icon class="el-input__icon" style="color: #1890ff"><Avatar /></el-icon>
  14. </template>
  15. </el-input>
  16. </el-form-item>
  17. <el-form-item prop="password">
  18. <el-input v-model="state.password" name="password" type="password" class="w-50 m-2" placeholder="请输入密码" show-password>
  19. <template #prefix>
  20. <el-icon class="el-input__icon" style="color: #1890ff"><Lock /></el-icon>
  21. </template>
  22. </el-input>
  23. </el-form-item>
  24. <el-form-item prop="remember">
  25. <el-checkbox v-model="state.remember" label="1" size="large">自动登录</el-checkbox>
  26. </el-form-item>
  27. <el-form-item>
  28. <el-button type="primary" style="width: 100%" @click="onSubmit()">登录</el-button>
  29. </el-form-item>
  30. </el-form>
  31. </div>
  32. </div>
  33. </template>
  34. <script setup>
  35. import {reactive} from 'vue';
  36. import { useRouter } from 'vue-router';
  37. import {Login} from '../network/index.js';
  38. import { ElMessage } from 'element-plus'
  39. //这是向服务器请求时所输入的数据,创建登录时的state,与本文11,18,25行相对应
  40. const state = reactive({
  41. account : "",
  42. password : "",
  43. remember : true
  44. });
  45. //定义路由器
  46. const router = useRouter();
  47. //从浏览器存储里获取用户登录时的数据;uid
  48. //const uid=window.localStorage.getItem("uid");
  49. const ticket=window.localStorage.getItem("ticket");
  50. //如果有票据就跳转到首页
  51. if(ticket){
  52. ElMessage({ //增加这一条就不会跳转到登录页面了
  53. message:'您已登录',
  54. type:'success'
  55. });
  56. router.push("/");
  57. }
  58. //提交,onSubmit与28行相对应
  59. const onSubmit=()=>{
  60. console.log(state);//先打印一下数据
  61. Login(state).then((e)=>{ //state是传值,e是返回值
  62. console.log(e);
  63. if(e.code==0){ //如果e的值为0时,则登录成功
  64. ElMessage({
  65. message:e.msg,
  66. type:'success'
  67. });
  68. //把登录时的数据保存到浏览器的存储中
  69. //window.localStorage.setItem('uid',e.data.uid);
  70. window.localStorage.setItem('ticket',e.data.ticket);
  71. window.localStorage.setItem('name',e.data.name);
  72. //路由器跳转到首页
  73. router.push("/");
  74. }else{ //反之登录不成功
  75. ElMessage({
  76. message:e.msg,
  77. type:'error'
  78. });
  79. }
  80. })
  81. }
  82. // const router = useRouter();
  83. // const ticket = window.localStorage.getItem("ticket");
  84. // if(ticket){
  85. // ElMessage({
  86. // message: '您已登录',
  87. // type: 'success'
  88. // });
  89. // router.push("/");
  90. // }
  91. // const onSubmit = ()=>{
  92. // Login(state).then( (e)=>{
  93. // console.log(e.data);
  94. // if(e.code == 0){
  95. // ElMessage({
  96. // message: e.msg,
  97. // type: 'success'
  98. // });
  99. // 登录完成以后
  100. // window.localStorage.setItem("ticket",e.data.ticket);
  101. // window.localStorage.setItem("name",e.data.name);
  102. // router.push("/");
  103. // }else{
  104. // ElMessage({
  105. // message: e.msg,
  106. // type: 'error'
  107. // });
  108. // }
  109. // } )
  110. // }
  111. </script>
  112. <style>
  113. .container {
  114. position: relative;
  115. width: 100%;
  116. min-height: 100%;
  117. padding: 110px 0 144px;
  118. background-repeat: no-repeat;
  119. background-position: center 110px;
  120. background-size: 100%;
  121. }
  122. .main {
  123. width: 368px;
  124. min-width: 260px;
  125. margin: 50px auto;
  126. }
  127. .el-icon {
  128. color: #359eff;
  129. }
  130. </style>
3.前台用户文件:user.vue
  1. <template>
  2. <div style="margin:0 0 20px 0;">
  3. <!-- 当添加按钮点击时调用add方法并传一个为0的值 -->
  4. <el-button type="success" size="large" @click="add(0)">添加</el-button>
  5. </div>
  6. <el-form label-width="120px" :inline="true">
  7. <el-form-item label="搜索项">
  8. <el-select placeholder="请选择您要搜索的项">
  9. <el-option label="姓名" value="" />
  10. <el-option label="手机" value="" />
  11. </el-select>
  12. </el-form-item>
  13. <el-form-item>
  14. <el-button type="primary">搜索</el-button>
  15. </el-form-item>
  16. </el-form>
  17. <el-table :data="tableData.lists" border style="width: 100%" size="large">
  18. <el-table-column prop="uid" label="ID" />
  19. <el-table-column prop="account" label="账号" />
  20. <el-table-column prop="name" label="姓名" />
  21. <el-table-column prop="phone" label="手机号" />
  22. <el-table-column prop="status" label="状态" />
  23. <el-table-column prop="add_time" label="入职时间" />
  24. <el-table-column prop="last_time" label="最后登录时间" />
  25. <el-table-column label="操作">
  26. <template #default="scope">
  27. <el-button size="small" type="primary" @click="add(scope.row)">修改</el-button>
  28. <!-- <el-button size="small" type="danger">删除</el-button> -->
  29. <el-popconfirm title="确认删除吗?" @confirm="del(scope.row)">
  30. <template #reference>
  31. <el-button size="small" type="danger">删除</el-button>
  32. </template>
  33. </el-popconfirm>
  34. </template>
  35. </el-table-column>
  36. </el-table>
  37. <!-- 弹出的对话框(弹窗) -->
  38. <el-dialog v-model="data.is_form" :title="data.title" width="30%">
  39. <!-- 弹窗中的表单 -->
  40. <el-form :model="fromData" label-width="120px" size="small">
  41. <el-form-item label="账号">
  42. <el-input v-model="fromData.account"/>
  43. </el-form-item>
  44. <el-form-item label="密码">
  45. <el-input v-model="fromData.password" type="password" show-password :placeholder="data.plac"/>
  46. </el-form-item>
  47. <el-form-item label="姓名">
  48. <el-input v-model="fromData.name"/>
  49. </el-form-item>
  50. <el-form-item label="手机号">
  51. <el-input v-model="fromData.phone"/>
  52. </el-form-item>
  53. <el-form-item label="状态">
  54. <el-select v-model="fromData.status" placeholder="请选择状态">
  55. <el-option label="开启" :value="1" />
  56. <el-option label="关闭" :value="0" />
  57. </el-select>
  58. </el-form-item>
  59. <el-form-item label="入职时间">
  60. <el-date-picker
  61. v-model="fromData.add_time"
  62. type="date"
  63. placeholder="选一日期"
  64. :size="size"
  65. />
  66. </el-form-item>
  67. <el-form-item label="最后登录时间">
  68. <el-date-picker
  69. v-model="fromData.last_time"
  70. type="date"
  71. placeholder="选一日期"
  72. :size="size"
  73. />
  74. </el-form-item>
  75. <!-- '确定'按钮 -->
  76. <el-button type="success" size="largr" @click="fun">确定</el-button>
  77. </el-form>
  78. </el-dialog>
  79. </template>
  80. <script setup>
  81. //从vue中引入响应式数据reactive(数据改变后视图也会自动更新,就叫响应式数据)
  82. import {reactive} from 'vue';
  83. import axios from "axios";
  84. //引入index.js文件中的UserLists,UserSave方法
  85. import {UserLists,UserSave,UserDel} from "../../network/index.js"
  86. // 引入element组件中的消息框
  87. import { ElMessage } from 'element-plus';
  88. // 引入element组件中的告示框
  89. import { alertProps } from 'element-plus';
  90. //运用票据(ticket),还要引入下面路由
  91. import { useRouter } from 'vue-router';
  92. //获取票据(ticket)
  93. const ticket=window.localStorage.getItem('ticket');
  94. const router=useRouter();
  95. //增加下面这一条就不能随便打开用户文件了,要先登录才行
  96. if(!ticket){
  97. ElMessage({
  98. message:'请先登录',
  99. type:'error'
  100. });
  101. router.push("/login");
  102. }
  103. // reactive表示data下有多个值,如data.is_form,data.title
  104. const data=reactive({
  105. is_form:false,
  106. title:"添加",
  107. plac:"请输入密码",
  108. });
  109. const fromData=reactive({
  110. uid : 0,
  111. account:'',
  112. password:'',
  113. name:'',
  114. phone:'',
  115. add_time:'',
  116. last_time:'',
  117. status:1,
  118. });
  119. const tableData=reactive({
  120. lists:[]
  121. });
  122. UserLists().then((e)=>{
  123. tableData.lists=e;
  124. })
  125. // 添加和修改弹框
  126. const add=(e)=>{ //e传一个0的值(看第4行)
  127. console.log(e);
  128. data.is_form=true;//
  129. if(e!=0){
  130. data.title="修改";
  131. data.plac = "密码如果不修改,可以不填写"
  132. fromData.account=e.account;
  133. fromData.name=e.name;
  134. fromData.phone=e.phone;
  135. fromData.password="";
  136. fromData.uid = e.uid;
  137. }else{
  138. data.title="添加";
  139. data.plac = "请输入密码";
  140. fromData.account="";
  141. fromData.name="";
  142. fromData.phone="";
  143. fromData.add_time="";
  144. fromData.last_time="";
  145. fromData.password="";
  146. fromData.uid = 0;
  147. }
  148. }
  149. //'确定'按钮点击时调用以下fun方法
  150. const fun=()=>{
  151. console.log(fromData);
  152. UserSave(fromData).then((e)=>{
  153. //console.log(e);
  154. // alert(e.msg);
  155. // console.log(fromData.add_time);
  156. // console.log(fromData.last_time);
  157. data.is_form=false;//弹窗关闭
  158. UserLists().then((e)=>{
  159. tableData.lists=e;
  160. })
  161. if(e.code==0){
  162. ElMessage({
  163. message: e.msg,
  164. type: 'success',
  165. })
  166. }else{
  167. ElMessage({
  168. message: e.msg,
  169. type: 'error',
  170. })
  171. }
  172. })
  173. // data.is_form=false;//弹窗关闭
  174. // UserLists().then((e)=>{
  175. // tableData.lists=e;
  176. // })
  177. }
  178. const del=(e)=>{
  179. console.log(e);
  180. UserDel({uid:e.uid}).then((e)=>{
  181. if(e.code==0){
  182. ElMessage({
  183. message:e.msg,
  184. type:'success'
  185. });
  186. }else{
  187. ElMessage({
  188. message:e.msg,
  189. type:'error'
  190. });
  191. }
  192. UserLists().then((e)=>{
  193. tableData.lists=e;
  194. })
  195. })
  196. }
  197. </script>
4.前台的index文件:index.js
  1. import { request } from "../network/request.js";
  2. // export function index(){
  3. // return request({
  4. // url:"Api2/index",
  5. // method:"get",
  6. // })
  7. // }
  8. //查询用户列表接口
  9. export function UserLists(){
  10. return request({
  11. url:"Api2/UserLists",
  12. method:"post",
  13. })
  14. }
  15. // 添加用户数据接口
  16. export function UserSave(data){
  17. //header("Access-Control-Allow-Origin:*");
  18. return request({
  19. url:"Api2/UserSave",
  20. method:"post",
  21. data:data
  22. })
  23. }
  24. // 删除用户数据接口
  25. export function UserDel(data){
  26. return request({
  27. url:"Api2/UserDel",
  28. method:"post",
  29. data:data
  30. })
  31. }
  32. //创建登录接口
  33. export function Login(data){
  34. return request({
  35. url:"Api2/Login",
  36. method:"post",
  37. data:data
  38. })
  39. }
5.后台Api文件:Api2.php
  1. <?php
  2. namespace app\controller;
  3. use app\BaseController;
  4. use ouyangke\Ticket;
  5. // *要使用Db类必须使用门面方式( think\facade\Db )调用
  6. use think\facade\Db;
  7. // *引用门面方式的请求类
  8. use think\facade\Request;
  9. class Api2 extends BaseController{
  10. //public function index(){
  11. //header("Access-Control-Allow-Origin:*");
  12. //------------------------------------
  13. // echo 333;
  14. //------------------------------------
  15. // json格式,叫json字符串,在php中,不方便创建,先创建数组,用数组转成json格式
  16. //------------------------------------
  17. // $json = '{
  18. // ouyangke => "欧阳克"
  19. // }';
  20. // echo $json;
  21. //------------------------------------
  22. // 数组格式
  23. // $arr = [
  24. // [
  25. // 'uid' => 1,
  26. // 'name' => '欧阳克'
  27. // ],
  28. // [
  29. // 'uid' => 2,
  30. // 'name' => '朱天蓬'
  31. // ]
  32. // ];
  33. // print_r($arr);
  34. //------------------------------------
  35. // 把数组转换成json格式
  36. // $arr = [
  37. // [
  38. // 'uid' => 1,
  39. // 'name' => '欧阳克'
  40. // ],
  41. // [
  42. // 'uid' => 2,
  43. // 'name' => '朱天蓬'
  44. // ]
  45. // ];
  46. // $json = json_encode($arr);
  47. // print_r($json);
  48. // [{"uid":1,"name":"\u6b27\u9633\u514b"},{"uid":2,"name":"\u6731\u5929\u84ec"}]
  49. //------------------------------------
  50. // 使用var_dump判断json是一个字符串////------------------------------------//------------------------------------ // 打印json数据的类型,是字符串
  51. // $arr = [
  52. // [
  53. // 'uid' => 1,
  54. // 'name' => '欧阳克'
  55. // ],
  56. // [
  57. // 'uid' => 2,
  58. // 'name' => '朱天蓬'
  59. // ]
  60. // ];
  61. // $json = json_encode($arr);
  62. // var_dump($json);
  63. // string(77) "[{"uid":1,"name":"\u6b27\u9633\u514b"},{"uid":2,"name":"\u6731\u5929\u84ec"}]"
  64. //------------------------------------
  65. // 把json转换为数组的形式
  66. // $json = '[{"uid":1,"name":"\u6b27\u9633\u514b"},{"uid":2,"name":"\u6731\u5929\u84ec"}]';
  67. // $array = json_decode($json,true);
  68. // print_r($array);
  69. //------------------------------------
  70. // 用户表转换为数组形式
  71. //$arr_user = Db::table('bew_user')->select()->toArray();
  72. //打印
  73. // print_r($arr_user);
  74. // if(!empty( $arr_user)){
  75. // foreach( $arr_user as &$user_v){
  76. // if($user_v['status'] == 1){
  77. // $user_v['status_s'] = '开启';
  78. // }else{
  79. // $user_v['status_s'] = '关闭';
  80. // }
  81. // //把时间的值由时间戳改为年月日
  82. // $user_v['add_time'] = date('Y-m-d',$user_v['add_time']);
  83. // $user_v['last_time'] = date('Y-m-d',$user_v['last_time']);
  84. // }
  85. // }
  86. // 用户表由数组形式转换为json形式
  87. //$json_user = json_encode( $arr_user);
  88. //输出
  89. // echo $json_user;
  90. //也可以打印的方法
  91. // print_r($json_user);
  92. //------------------------------------
  93. //}
  94. //从前台的查询用户列表接口转到后台这用户列表方法
  95. public function UserLists(){
  96. //header("Access-Control-Allow-Origin:*");
  97. // 用户表转换为数组形式
  98. $arr_user = Db::table('bew_user')->select()->toArray();
  99. if (!empty($arr_user)) {
  100. foreach ($arr_user as & $user_v) {
  101. if ($user_v['status'] == 1) {
  102. $user_v['status'] = '开启';
  103. } else {
  104. $user_v['status'] = '关闭';
  105. }
  106. //把时间的值由时间戳改为年月日
  107. $user_v['add_time'] = date('Y-m-d', $user_v['add_time']);
  108. $user_v['last_time'] = date('Y-m-d', $user_v['last_time']);
  109. }
  110. }
  111. // 用户表由数组形式转换为json形式
  112. $json_user = json_encode($arr_user);
  113. //输出
  114. // echo $json_user;
  115. //也可以打印的方法
  116. print_r($json_user);
  117. }
  118. //从前台的添加用户接口转到后台这添加用户方法
  119. public function UserSave(){
  120. //$post相当于前台的弹窗表单
  121. $post=input('post.');
  122. //print_r($post);
  123. if ($post['uid']==0) {
  124. $data=[ //以下$data就是要传的数据
  125. 'account' => $post['account'],//如'account'是$post下的'account'传过来的
  126. 'password'=>md5($post['password']),
  127. 'name' => $post['name'],
  128. 'phone' => $post['phone'],
  129. 'status' => $post['status'],
  130. // 'add_time'=>time(),//time()表示当前日期
  131. //strtotime表示获取某个时间的时间戳
  132. 'add_time'=>strtotime($post['add_time']),
  133. // 'last_time'=>strtotime($post['last_time'])//数据库中如果对该字段(add_time)设为不可null,则该项就要加上去(即不能注释)
  134. 'last_time'=>strtotime($post['last_time']),
  135. ];
  136. // print_r ($data);
  137. $insert = Db::table('bew_user')->insert($data);
  138. if (empty($insert)) {
  139. $arr=[
  140. 'code'=>1,//以上添加中的插入语句通常返回为code码,有0或1,0表示成功,1表示失败,这里用数组包括0及1
  141. 'msg'=>'失败'
  142. ];
  143. } else {
  144. $arr=[
  145. 'code'=>0,
  146. 'msg'=>'成功'
  147. ];
  148. }
  149. echo json_encode($arr);// 由数组形式转换为json形式
  150. }else{
  151. $data=[ //以下$data就是要传的数据
  152. //'uid'=>$post['uid'],
  153. 'account' => $post['account'],//如'account'是$post下的'account'传过来的
  154. //密码不修改
  155. // 'password'=>md5($post['password']),
  156. 'name' => $post['name'],
  157. 'phone' => $post['phone'],
  158. 'status' => $post['status'],
  159. 'add_time'=>strtotime($post['add_time']),
  160. 'last_time'=>strtotime($post['last_time']),
  161. ];
  162. if(!empty($post['password'])){
  163. //当修改对象时不使其密码为空
  164. $data['password']=md5($post['password']);
  165. }
  166. $user=Db::table('bew_user')->where('uid',$post['uid'])->update($data);
  167. if (empty($user)) {
  168. $arr=[
  169. 'code'=>1,//以上添加中的插入语句通常返回为code码,有0或1,0表示成功,1表示失败,这里用数组包括0及1
  170. 'msg'=>'修改失败'
  171. ];
  172. } else {
  173. $arr=[
  174. 'code'=>0,
  175. 'msg'=>'修改成功'
  176. ];
  177. }
  178. echo json_encode($arr);// 由数组形式转换为json形式
  179. }
  180. }
  181. //从前台的删除用户接口转到后台这删除用户方法
  182. public function UserDel(){
  183. $uid=input('post.uid');
  184. if(empty($uid)){
  185. $arr=[
  186. 'code'=>1,
  187. 'msg'=>'请选择用户'
  188. ];
  189. echo json_encode($arr);
  190. exit;
  191. }
  192. $del=Db::table('bew_user')->where('uid',$uid)->delete();
  193. if(empty($del)){
  194. $arr=[
  195. 'code'=>1,
  196. 'msg'=>'删除失败'
  197. ];
  198. echo json_encode($arr);
  199. exit;
  200. }else{
  201. $arr=[
  202. 'code'=>0,
  203. 'msg'=>'删除成功'
  204. ];
  205. echo json_encode($arr);
  206. }
  207. }
  208. //从前台的登录接口转到后台这登录方法
  209. public function Login(){
  210. $post=input('post.');//接收这post
  211. if(empty($post['account'])){ //如果接收的post中的账号为空
  212. $arr=[
  213. 'code'=>1,
  214. 'msg'=>'账户不能为空'
  215. ];
  216. echo json_encode($arr);
  217. exit;
  218. }
  219. if(empty($post['password'])){ //如果接收的post中的密码为空
  220. $arr=[
  221. 'code'=>1,
  222. 'msg'=>'密码不能为空'
  223. ];
  224. echo json_encode($arr);
  225. exit;
  226. }
  227. //根据所接收的账号,查询bew_user表,并返回给变量$user
  228. $user=Db::table('bew_user')->where('account',$post['account'])->find();
  229. //print_r($user);//把它打印出来
  230. if(empty($user)){ //判断变量$user是否为空
  231. $arr=[
  232. 'code'=>1,
  233. 'msg'=>'未找到账户'
  234. ];
  235. echo json_encode($arr);
  236. exit;
  237. }
  238. if($user['password']!=md5($post['password'])){
  239. $arr=[
  240. 'code'=>1,
  241. 'msg'=>'密码错误'
  242. ];
  243. echo json_encode($arr);
  244. exit;
  245. }
  246. // unset($user['password']);//登录时数据中不显示密码(暂时打开)
  247. //票据调用创建(create())方法,把$user下面的uid传过来,关键词是phpcn,最后返回一个票据$ticket
  248. $ticket=Ticket::create($user['uid'],'phpcn');
  249. // print_r($ticket); //暂时打开
  250. //echo Ticket::get($ticket,'phpcn');//把32位加密传回去,然后再输出出来(暂时打开)
  251. $user['ticket'] = $ticket;
  252. unset($user['password'],$user['uid']);//登录时数据中不显示密码与用户的uid
  253. $arr = [
  254. 'code' => 0,
  255. 'msg' => '登录成功',
  256. 'data' => $user
  257. ];
  258. echo json_encode($arr);
  259. }
  260. }
6.后台的Ticket文件:Ticket.php
  1. <?php
  2. namespace ouyangke;
  3. /**
  4. * ticket
  5. * @author ouyangke
  6. */
  7. // Tickey(票据)其作用是考虑数据安全,这里是不直接显示uid,并对uid进行加密
  8. class Ticket {
  9. /**
  10. * 只允许静态调用
  11. */
  12. // final private function __construct() {
  13. // throw new ThinkException('只允许静态调用');
  14. // }
  15. /**
  16. * 创建ticket(即门票的意思)
  17. *
  18. * @param integer $uid 用户id
  19. * @param integer $bind 关键词
  20. * @param number $time 有效期
  21. * @param string $durable
  22. * @return multitype:number string
  23. */
  24. //静态的创建方法(由于是静态,故可用'::'进行访问及调用,其中7*24*60*60表示7天有效期,$durable为判断)
  25. // public static function create($uid, $bind="ouyangke",$time=7*24*60*60, $durable = false) {
  26. public static function create($uid, $bind="ouyangke",$time=1*1*1*60, $durable = false) {
  27. $expire = time() + $time;
  28. //调用_genKey方法(即加密成一个key,现返回给$key)
  29. $key = self::_genKey($uid, $bind, $expire);
  30. // 然后把上面的$bind, $uid, $key, $expire, $durable传到以下这个生成门票的方法中
  31. // 以下通过调用生成门票方法,然后就生成一个票据($ticket)
  32. $ticket = self::_buildTicket($bind, $uid, $key, $expire, $durable);
  33. return $ticket;
  34. }
  35. /**
  36. * 获取ticket信息
  37. *
  38. * @param integer $ticket
  39. * @param boolean $checked
  40. * @return Ambigous <mixed, NULL, multitype:number >
  41. */
  42. // 静态获取票据方法(把票据传过来)
  43. public static function get($ticket, $bind, $checked = false) {
  44. $checked || self::checkFormat($ticket);
  45. $uid = 0;
  46. $key = 0;
  47. $expire = 0;
  48. $durable = false;
  49. // 把以下这些数据进行解密
  50. $info = self::_parseTicket($ticket, $bind, $uid, $key, $expire, $durable);
  51. if (time() < $expire) {
  52. $info = array();
  53. $info['uid'] = $uid;
  54. $info['expire'] = $expire;
  55. return $uid; //最后返回uid
  56. }
  57. return false;
  58. }
  59. /**
  60. * 生成ticket
  61. * @param string $bind
  62. * @param integer $uid
  63. * @param integer $key
  64. * @param integer $expire
  65. * @param boolean $durable
  66. * @return string
  67. */
  68. //生成门票的方法
  69. protected static function _buildTicket($bind, $uid, $key, $expire, $durable = false) {
  70. $uBit = decbin($uid);
  71. $uLen = strlen($uBit);
  72. $eBit = sprintf('%032b', $expire);
  73. $kBit = sprintf('%032b', $key);
  74. $rBit = sprintf('%058s%05b%d', substr(base_convert(substr(md5(uniqid(mt_rand(), true)), mt_rand(0, 16), 16), 16, 2), 0, 58), $uLen % 32, $durable ? 1 : 0);
  75. $cBit = sprintf('%032b', crc32($uBit . $eBit . $kBit . $rBit . $bind));
  76. $uBit .= substr(sprintf('%032b', mt_rand()), $uLen - 32);
  77. $bin = '';
  78. for ($i = 0; $i < 32; $i++) {
  79. $bin .= $rBit[$i * 2];
  80. $bin .= $eBit[$i];
  81. $bin .= $kBit[$i];
  82. $bin .= $rBit[$i * 2 + 1];
  83. $bin .= $uBit[$i];
  84. $bin .= $cBit[$i];
  85. }
  86. // 然后再进行加密并返回
  87. return strtr(base64_encode(implode('', array_map(function($item){ return chr(bindec($item)); }, str_split($bin, 8)))), '+/', '-_');
  88. }
  89. /**
  90. * 解析Ticket
  91. *
  92. * @param string $ticket
  93. * @param string $bind
  94. * @param integer $uid
  95. * @param integer $key
  96. * @param integer $expire
  97. * @param boolean $durable
  98. * @return boolean
  99. */
  100. protected static function _parseTicket($ticket, $bind, &$uid = NULL, &$key = NULL, &$expire = NULL, &$durable = NULL) {
  101. $rBit = '';
  102. $eBit = '';
  103. $kBit = '';
  104. $uBit = '';
  105. $cBit = '';
  106. $bin = implode('', array_map(function($item){ return sprintf('%08b', ord($item)); }, str_split(base64_decode(strtr($ticket, '-_', '+/')), 1)));
  107. for ($i = 0; $i < 192; $i += 6) {
  108. $rBit .= $bin[$i];
  109. $eBit .= $bin[$i + 1];
  110. $kBit .= $bin[$i + 2];
  111. $rBit .= $bin[$i + 3];
  112. $uBit .= $bin[$i + 4];
  113. $cBit .= $bin[$i + 5];
  114. }
  115. $uLen = bindec(substr($rBit, 58, 5));
  116. if ($uLen < 32) {
  117. $uBit = substr($uBit, 0, $uLen);
  118. }
  119. if (sprintf('%u', crc32($uBit . $eBit . $kBit . $rBit . $bind)) == bindec($cBit)) {
  120. $uid = bindec($uBit);
  121. if ($uid > 0) {
  122. $expire = bindec($eBit);
  123. $key = bindec($kBit);
  124. $durable = ($rBit[63] === '1');
  125. return true;
  126. }
  127. }
  128. // throw new ThinkException('Ticket error');
  129. }
  130. /**
  131. * 生成key
  132. *
  133. * @param integer $uid
  134. * @param string $bind
  135. * @param integer $expire
  136. * @return integer
  137. */
  138. //_genKey方法其作用是加密成一个key(键)
  139. // 先用'%d|%s|%d',替换掉$uid, $bind, $expire,然后用md5进行加密,最后使用32位数据进行处理并返回
  140. protected static function _genKey($uid, $bind, $expire) {
  141. return crc32(md5(sprintf('%d|%s|%d', $uid, $bind, $expire), true));
  142. }
  143. /**
  144. * 发送ticket http头
  145. *
  146. * @param string $ticket
  147. * @param integer $uid
  148. * @param integer $ttl
  149. */
  150. // protected static function _headerTicket($ticket, $uid, $ttl) {
  151. // header(sprintf('Set-Ticket: %s; uid=%d; expires=%s; Max-Age=%d', $ticket, $uid, Request::httpDate(time() + $ttl), $ttl));
  152. // }
  153. /**
  154. * 判断格式是否正确
  155. *
  156. * @param string $ticket
  157. * @return boolean
  158. */
  159. protected static function _isTicket($ticket) {
  160. return strlen($ticket) == 32 && strspn($ticket, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_') == 32;
  161. }
  162. /**
  163. * 检查格式是否正确
  164. *
  165. * @param string $ticket
  166. */
  167. public static function checkFormat($ticket) {
  168. if (!self::_isTicket($ticket)) {
  169. return false;
  170. }
  171. }
  172. }
题目1:登录功能与及使用token对uid的加密

1

2

3

4

题目2:管理员对数据的修改

1

2

3

4

题目3:管理员对数据的删除

1

2

3

【转自:美国cn2服务器 http://www.558idc.com/mg.html欢迎留下您的宝贵建议】