PHP8.1.21版本已发布
vue8.1.21版本已发布
jquery8.1.21版本已发布

博客列表 > 用户管理加登录验证、注册、管理权限

用户管理加登录验证、注册、管理权限

吳
原创
2021年03月03日 12:55:54 2621浏览
  • 注册新用户

  • 登录跳转

  • 普通用户无编辑删除权限

1.前端渲染页:index.php

  1. <?php
  2. session_start();
  3. ?>
  4. <!DOCTYPE html>
  5. <html lang="en">
  6. <head>
  7. <meta charset="UTF-8">
  8. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  9. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  10. <title>用户管理系统</title>
  11. <link rel="stylesheet" href="style.css">
  12. <style>
  13. header {
  14. display: flex;
  15. background-color: #333;
  16. padding: 0.5em 1em;
  17. width: 100%;
  18. }
  19. a {
  20. color: #bbb;
  21. text-decoration: none;
  22. }
  23. a:hover {
  24. color: white;
  25. }
  26. header nav {
  27. margin-left: auto;
  28. }
  29. </style>
  30. </head>
  31. <body>
  32. <header>
  33. <a href="#">首页</a>
  34. <nav>
  35. <?php if (!isset($_SESSION['email'])) : ?>
  36. <script>
  37. alert('请登录后再操作!');
  38. location.href = "login.php";
  39. </script>
  40. <?php else : ?>
  41. <a href="#" class="ses"><?= $_SESSION['email'] ?></a>
  42. <a href="handle.php?action=logout">退出</a>
  43. <?php endif ?>
  44. </nav>
  45. </header>
  46. <table>
  47. <caption>用户管理 <span class="tips" style="color:red;font-size:10px;"></span></caption>
  48. <thead>
  49. <tr>
  50. <td>UID</td>
  51. <td>用户名</td>
  52. <td>邮箱</td>
  53. <td>注册时间</td>
  54. <?php if ($_SESSION['email'] === 'guest1@php.cn') : ?>
  55. <td>操作</td>
  56. <? endif ?>
  57. </tr>
  58. </thead>
  59. <!-- 列表渲染 -->
  60. <tbody></tbody>
  61. </table>
  62. <!-- 分页渲染 -->
  63. <p></p>
  64. <!-- 模态框编辑 -->
  65. <div class="md">
  66. <div class="md-drop"></div>
  67. <div class="md-body">
  68. <button class="close">关闭</button>
  69. <form action="" name="editform">
  70. <h2>编辑用户</h2>
  71. <div class="md-login">
  72. <label for="name">姓名:</label>
  73. <input type="text" name="name" id="name" value="">
  74. <label for="email">邮箱:</label>
  75. <input type="email" name="email" id="email" value="">
  76. <button class="save">保存</button>
  77. </div>
  78. </form>
  79. </div>
  80. </div>
  81. <!-- 模态框样式 -->
  82. <style>
  83. /* 模态框初始化隐藏 */
  84. .md {
  85. display: none;
  86. }
  87. /* 遮罩层 */
  88. .md .md-drop {
  89. position: fixed;
  90. background-color: rgb(0, 0, 0, .5);
  91. top: 0;
  92. left: 0;
  93. right: 0;
  94. bottom: 0;
  95. }
  96. .md .md-body {
  97. position: fixed;
  98. background-color: lightcyan;
  99. padding: 1em;
  100. overflow: hidden;
  101. max-width: 25em;
  102. max-height: 20em;
  103. /* 水平垂直居中 */
  104. top: 0;
  105. left: 0;
  106. right: 0;
  107. bottom: 0;
  108. margin: auto;
  109. border-radius: 10px;
  110. }
  111. /* 关闭按钮 */
  112. .md .md-body .close {
  113. float: right;
  114. height: 2.5em;
  115. width: 3em;
  116. border: 0;
  117. border-radius: 0.5em;
  118. outline: none;
  119. background-color: rgb(1, 231, 135);
  120. }
  121. .md .md-login {
  122. display: grid;
  123. gap: 1em;
  124. margin-top: 20px;
  125. }
  126. </style>
  127. <script src="ajax.js"></script>
  128. </body>
  129. </html>

2. 登录页:login.php

  1. <?php
  2. session_start();
  3. if(isset($_SESSION['email'])) {
  4. echo '<script>alert("请不要重复登录");location.href="index.php";</script>';
  5. }
  6. ?>
  7. <!DOCTYPE html>
  8. <html lang="en">
  9. <head>
  10. <meta charset="UTF-8">
  11. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  12. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  13. <title>登录</title>
  14. <style>
  15. form {
  16. display: grid;
  17. gap: .5em;
  18. width: 15em;
  19. margin: 2em auto;
  20. border: 1px solid #eee;
  21. padding: 1em 2em;
  22. background-color: lightskyblue;
  23. border-radius: 0.5em;
  24. }
  25. </style>
  26. </head>
  27. <body>
  28. <form name="login">
  29. <span>用户登录</span>
  30. <input type="email" name="email" placeholder="请输入登录邮箱">
  31. <input type="password" name="password" placeholder="请输入登录密码">
  32. <!-- 此处给button类型防止默认提交 -->
  33. <button type="button" name="submit">立即登录</button>
  34. <button type="button" name="registers">新用户注册</button>
  35. <span class="tips"></span>
  36. </form>
  37. <script>
  38. const form = document.forms.login;
  39. const email = form.email;
  40. const psw = form.password;
  41. const submitBtn = form.submit;
  42. const xhr = new XMLHttpRequest;
  43. const tips = document.querySelector('.tips');
  44. const regis = form.registers;
  45. regis.onclick = (ev) => {
  46. location.href = 'register.php';
  47. }
  48. submitBtn.onclick = (ev) => {
  49. // 非空判断
  50. if (email.value.trim().length > 0 && psw.value.trim().length >0) {
  51. // 请求参数
  52. xhr.open('post','handle.php?action=login');
  53. // 响应类型
  54. // 设置类型为json,返回结果自动解析为js对象
  55. xhr.responseType = 'json';
  56. // 成功回调
  57. xhr.onload = () => {
  58. console.log(xhr.response);
  59. tips.innerHTML = xhr.response.msg;
  60. if (xhr.response.status === 1 ) {
  61. // 登录成功进入用户管理页
  62. setTimeout(() => location.href = 'index.php',3000);
  63. }
  64. }
  65. // 失败回调
  66. xhr.onerror = () => console.log('error!');
  67. // 发送请求
  68. xhr.send(new FormData(form));
  69. } else {
  70. tips.innerHTML = '账户信息不能为空!';
  71. email.focus();
  72. }
  73. }
  74. // 清空提示
  75. [email,psw].forEach((item)=>item.oninput = () => tips.innerHTML = null);
  76. </script>
  77. </body>
  78. </html>

3. 注册页:register.php

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>新用户注册</title>
  8. <style>
  9. form {
  10. display: grid;
  11. gap: .5em;
  12. width: 15em;
  13. margin: 2em auto;
  14. border: 1px solid #eee;
  15. padding: 1em 2em;
  16. background-color: lightskyblue;
  17. border-radius: 0.5em;
  18. }
  19. </style>
  20. </head>
  21. <body>
  22. <form name="register">
  23. <span>新用户注册</span>
  24. <input type="text" name="name" placeholder="请输入用户名">
  25. <input type="email" name="email" placeholder="请输入登录邮箱">
  26. <input type="password" name="password1" placeholder="请输入登录密码">
  27. <input type="password" name="password2" placeholder="确认登录密码">
  28. <!-- 此处给button类型防止默认提交 -->
  29. <button type="button" name="submit">立即注册</button>
  30. <span class="tips"></span>
  31. </form>
  32. <script>
  33. const form = document.forms.register;
  34. const name = form.name;
  35. const email = form.email;
  36. const psw1 = form.password1;
  37. const psw2 = form.password2;
  38. const submitBtn = form.submit;
  39. const xhr = new XMLHttpRequest;
  40. const tips = document.querySelector('.tips');
  41. submitBtn.onclick = (ev) => {
  42. // 非空判断
  43. if (name.value.trim().length > 0 && email.value.trim().length > 0 && psw1.value.trim().length >0) {
  44. if (psw1.value !== psw2.value) {
  45. tips.innerHTML = '确认密码输入不一致!';
  46. psw1.focus();
  47. } else {
  48. // 请求参数
  49. xhr.open('post','handle.php?action=register');
  50. // 响应类型
  51. // 设置类型为json,返回结果自动解析为js对象
  52. xhr.responseType = 'json';
  53. // 成功回调
  54. xhr.onload = () => {
  55. console.log(xhr.response);
  56. tips.innerHTML = xhr.response.msg;
  57. if (xhr.response.status === 1 ) {
  58. // 注册成功进入用户管理页
  59. setTimeout(() => location.href = 'index.php',3000);
  60. }
  61. }
  62. // 失败回调
  63. xhr.onerror = () => console.log('error!');
  64. // 确认密码不需要发送
  65. const data = new FormData(form);
  66. data.delete('password2');
  67. // 发送请求
  68. xhr.send(data);
  69. }
  70. } else {
  71. tips.innerHTML = '账户信息不能为空!';
  72. name.focus();
  73. }
  74. }
  75. // 清空提示
  76. [name,email,psw1,psw2].forEach((item)=>item.oninput = () => tips.innerHTML = null);
  77. </script>
  78. </body>
  79. </html>

4. css样式表:style.css

  1. * {
  2. margin: 0;
  3. padding: 0;
  4. box-sizing: border-box;
  5. color: #555;
  6. }
  7. body {
  8. display: flex;
  9. flex-direction: column;
  10. align-items: center;
  11. }
  12. /*表格样式*/
  13. table {
  14. width: 90%;
  15. border: 1px solid;
  16. border-collapse: collapse;
  17. text-align: center;
  18. }
  19. table caption {
  20. font-size: 1.2rem;
  21. margin: 10px;
  22. }
  23. table td,
  24. table th {
  25. border: 1px solid;
  26. padding: 5px;
  27. }
  28. table tr:hover {
  29. background-color: #eee;
  30. }
  31. table thead tr:only-of-type {
  32. background-color: lightcyan;
  33. }
  34. table button {
  35. width: 56px;
  36. height: 26px;
  37. }
  38. table button:last-of-type {
  39. color: red;
  40. }
  41. table button {
  42. cursor: pointer;
  43. margin: 0 3px;
  44. }
  45. /*分页条样式*/
  46. body > p {
  47. display: flex;
  48. }
  49. p > a {
  50. text-decoration: none;
  51. color: #555;
  52. border: 1px solid #888;
  53. padding: 5px 10px;
  54. margin: 10px 2px;
  55. }
  56. .active {
  57. background-color: seagreen;
  58. color: white;
  59. border: 1px solid seagreen;
  60. }

5. js文件:ajax.js

  1. // 页面载入完成时渲染第一页数据
  2. window.onload = function () {
  3. select(1);
  4. };
  5. // 编辑
  6. document.querySelector('table:first-of-type tbody').addEventListener('click' , ev => {
  7. // 获取记录id
  8. const sid = ev.target.parentNode.parentNode.querySelector('td').textContent * 1;
  9. const tips = document.querySelector('.tips');
  10. // 操作类型
  11. switch (ev.target.textContent) {
  12. case '编辑':
  13. // 显示模态框
  14. document.querySelector('.md').style.display = 'block';
  15. // 点击关闭按钮
  16. document.querySelector('.md .close').addEventListener('click',(eve) => {
  17. document.querySelector('.md').style.display = 'none';
  18. });
  19. // 点击模态框之外区域
  20. document.querySelector('.md .md-drop').addEventListener('click',(eve) => {
  21. document.querySelector('.md').style.display = 'none';
  22. });
  23. // 获取数据
  24. let name = ev.target.parentNode.parentNode.querySelector('td:nth-of-type(2)').textContent;
  25. let email = ev.target.parentNode.parentNode.querySelector('td:nth-of-type(3)').textContent;
  26. // 渲染到模态框
  27. document.getElementById('name').value = name;
  28. document.getElementById('email').value = email;
  29. // 编辑事件
  30. document.querySelector('.md .save').addEventListener('click',(eve) => {
  31. // 禁止默认提交
  32. eve.preventDefault();
  33. // 获取模态框数据
  34. name = document.getElementById('name').value;
  35. email = document.getElementById('email').value;
  36. // 创建对象
  37. let xhr = new XMLHttpRequest();
  38. // 配置参数
  39. xhr.open('post','api.php?action=update&sid=' + sid);
  40. xhr.responseType = 'json';
  41. // 处理请求
  42. xhr.onload = () => {
  43. // 更新数据写会页面
  44. tips.innerHTML = xhr.response.msg;
  45. if (xhr.response.status === 1 ) {
  46. document.querySelector('.md').style.display = 'none';
  47. ev.target.parentNode.parentNode.querySelector('td:nth-of-type(2)').textContent = name;
  48. ev.target.parentNode.parentNode.querySelector('td:nth-of-type(3)').textContent = email;
  49. setTimeout(() => tips.innerHTML = null,2000);
  50. }
  51. };
  52. xhr.send(new FormData(document.forms.namedItem('editform')));
  53. });
  54. break;
  55. case '删除':
  56. if (confirm('确认删除UID:' + sid + '用户?')) {
  57. // 创建对象
  58. let xhr = new XMLHttpRequest();
  59. // 配置参数
  60. xhr.open('get','api.php?action=delete&sid=' + sid);
  61. xhr.responseType = 'json';
  62. // 处理请求
  63. xhr.onload = () => {
  64. tips.innerHTML = xhr.response.msg;
  65. if (xhr.response.status === 1) {
  66. // 删除节点
  67. ev.target.parentNode.parentNode.remove();
  68. setTimeout(() => tips.innerHTML = null,2000);
  69. }
  70. };
  71. // 发送请求
  72. xhr.send(null);
  73. }
  74. break;
  75. }
  76. })
  77. function select(page = 1) {
  78. // 创建对象
  79. const xhr = new XMLHttpRequest();
  80. // 配置参数
  81. xhr.open('get', 'api.php?action=select&page=' + page);
  82. // 处理请求
  83. xhr.onload = () => {
  84. // console.log(xhr.response);
  85. let res = JSON.parse(xhr.response);
  86. let pages = res.pages;
  87. let users = res.users;
  88. // 渲染数据
  89. document.querySelector('table:first-of-type tbody').innerHTML = get_datas(users);
  90. // 渲染分页
  91. document.querySelector('p:first-of-type').innerHTML = pags(page,pages);
  92. }
  93. // 发送请求
  94. xhr.send(null);
  95. }
  96. // 渲染数据
  97. function get_datas(datas) {
  98. const ses = document.querySelector('.ses').innerText;
  99. let str = '';
  100. for (let i = 0; i < datas.length; i++) {
  101. str += '<tr>';
  102. str += '<td>' + datas[i]['sid'] + '</td>';
  103. str += '<td>' + datas[i]['name'] + '</td>';
  104. str += '<td>' + datas[i]['email'] + '</td>';
  105. str += '<td>' + datas[i]['create_at'] + '</td>';
  106. if (ses=== 'guest1@php.cn') {
  107. str += '<td><button>编辑</button><button>删除</button></td>';
  108. }
  109. str += '</tr>';
  110. }
  111. return str;
  112. }
  113. // 无刷新分页
  114. document.querySelector('p:first-of-type').addEventListener('click',ev => {
  115. // 禁用默认跳转
  116. ev.preventDefault();
  117. // 点击当前激活页,无效点击
  118. if (ev.target.classList.contains('active')) return;
  119. // 去掉激活样式
  120. [...ev.currentTarget.children].forEach(ele => ele.classList.remove('active'));
  121. // 当前页添加激活样式
  122. ev.target.classList.add('active');
  123. let url = ev.target.href,page;
  124. // 获取页码
  125. if (url.indexOf('?') !== -1) {
  126. page = url.split('=')[1];
  127. } else {
  128. page = 1;
  129. }
  130. select(page);
  131. })
  132. // 分页数据
  133. function pags (page = 1,pages) {
  134. let pag = '';
  135. let active = '';
  136. // 首页和上一页
  137. if (page <= 1) page =1;
  138. if (page != 1) {
  139. pag += '<a href="'+ document.URL + '?p=1">首页</a>';
  140. pag += '<a href="'+ document.URL + '?p=' + Math.max(1,page - 1) +'">上一页</a>';
  141. }
  142. // 高亮分页
  143. for (i = 1; i <= pages; i++ ) {
  144. active = '';
  145. if (page == i) active = 'class="active"';
  146. pag += '<a href="' + document.URL + '?p=' + i + '"' + active + '>' + i + '</a>';
  147. }
  148. // 下一页和尾页
  149. if (page >= pages) page = pages;
  150. if (page !== pages) {
  151. pag += '<a href="' + document.URL + '?p=' + Math.min(page + 1,pages) + '">下一页</a>'
  152. pag += '<a href="' + document.URL + '?p=' + pages +'">尾页</a>'
  153. }
  154. return pag;
  155. }

6. 文件:api.php

  1. $config = [
  2. 'type' => 'mysql',
  3. 'host' => '127.0.0.1',
  4. 'dbname' => 'phpedu',
  5. 'username' => 'root',
  6. 'password' => '123456',
  7. ];
  8. extract($config);
  9. $dsn = sprintf('%s:host=%s;dbname=%s;',$type,$host,$dbname);
  10. try {
  11. $pdo = new PDO($dsn,$username,$password);
  12. // 设置结果集返回类型
  13. $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC);
  14. // var_dump($pdo,'连接成功');
  15. } catch (PDOException $e){
  16. die('连接失败:'. $e->getMessage());
  17. }
  18. // 页码通过get请求
  19. $page = $_GET['page'] ?? 1;
  20. $action = $_GET['action'] ?? 'select';
  21. switch ($action) {
  22. // 查询
  23. case 'select':
  24. die(get_datas($pdo,$page));
  25. break;
  26. // 删
  27. case 'delete':
  28. die(del_data($pdo,$_GET['sid'] ?? 0));
  29. break;
  30. // 更新
  31. case 'update':
  32. $sid = $_GET['sid'] ?? 0;
  33. $name = $_POST['name'];
  34. $email = $_POST['email'];
  35. die(update_data($pdo,$sid,$name,$email));
  36. break;
  37. }
  38. // 更新
  39. function update_data($pdo,$sid,$name,$email) {
  40. if ($sid) {
  41. $sql = "UPDATE users SET name=:name, email=:email WHERE sid = :sid;";
  42. $stmt = $pdo->prepare($sql);
  43. $stmt->bindParam(':sid',$sid,PDO::PARAM_INT);
  44. $stmt->bindParam(':name',$name,PDO::PARAM_STR);
  45. $stmt->bindParam(':email',$email,PDO::PARAM_STR);
  46. $stmt->execute();
  47. if($stmt->rowCount() > 0) {
  48. return json_encode(['status' => 1,'msg' => '更新成功!']);
  49. }
  50. }
  51. return json_encode(['status' => 0,'msg' => '未知错误!']);
  52. }
  53. // 删除
  54. function del_data($pdo,$sid = 0) {
  55. if ($sid) {
  56. $sql = "DELETE FROM users WHERE sid = :sid;";
  57. $stmt = $pdo->prepare($sql);
  58. $stmt->bindParam(':sid',$sid,PDO::PARAM_INT);
  59. $stmt->execute();
  60. if ($stmt->rowCount() > 0) {
  61. return json_encode(['status' => 1,'msg' => '删除成功!']);
  62. }
  63. }
  64. return json_encode(['status' => 0,'msg' => '未知错误!']);
  65. }
  66. // 获取总页数
  67. function get_pages($pdo,$page = 1,$num = 5) {
  68. // 总页数
  69. $num = 5;
  70. $offset = ($page - 1 ) * $num;
  71. $sql = "SELECT CEIL(COUNT(1)/{$num}) total FROM users";
  72. $pages = $pdo->query($sql)->fetch()['total'];
  73. return $pages;
  74. }
  75. function get_datas($pdo,$page = 1, $num = 5) {
  76. // 获取总页数
  77. $pages = get_pages($pdo);
  78. // 每页显示数据
  79. $offset = ($page - 1) * $num;
  80. $sql = "SELECT * FROM `users` LIMIT {$offset},{$num}";
  81. $stmt = $pdo->prepare($sql);
  82. $stmt->execute();
  83. $users = $stmt->fetchAll();
  84. $users = $pdo->query($sql)->fetchall();
  85. return json_encode(['pages' => $pages, 'users' => $users]);
  86. }

7.登录验证:login.php

  1. // 开启session会话
  2. session_start();
  3. // 白名单
  4. $allurls = [
  5. 'index.php',
  6. 'login.php',
  7. 'register.php',
  8. 'api.php'
  9. ];
  10. $requrl = basename($_SERVER['HTTP_REFERER']);
  11. if(!isset($_SERVER['HTTP_REFERER']) || !in_array($requrl,$allurls)) {
  12. die('<script>alert("非法访问");location.href="index.php";</script>');
  13. }
  14. // 连接数据库
  15. $pdo = new PDO('mysql:dbname=phpedu','root','123456');
  16. $action = strtolower($_GET['action']);
  17. switch ($action) {
  18. // 登录
  19. case 'login':
  20. $sql = 'SELECT * FROM user WHERE email=:email AND password=md5(:password)';
  21. $stmt = $pdo->prepare($sql);
  22. if ($stmt->execute($_POST)) {
  23. if ($stmt->fetch()) {
  24. // 登录成功就将用户信息写入session
  25. $_SESSION['email'] = $_POST['email'];
  26. echo json_encode(['status' => 1, 'msg' => '登录成功,3秒后跳转...']);
  27. } else {
  28. echo json_encode(['status' => 0, 'msg' => '账号或密码错误!']);
  29. }
  30. } else {
  31. print_r($stmt->errorInfo());
  32. }
  33. break;
  34. // 注册
  35. case 'register':
  36. // 确保邮箱的唯一性,在后端做判断,不依赖数据库索引
  37. // 获取标中所有邮箱返回一个数组
  38. $stmt = $pdo->prepare('SELECT email FROM user');
  39. $stmt->bindColumn('email',$email);
  40. $stmt->execute();
  41. $emails = [];
  42. while ($stmt->fetch(PDO::FETCH_BOUND)) {
  43. $emails[] = $email;
  44. }
  45. // echo json_encode($emails);
  46. if (in_array($_POST['email'], $emails)) {
  47. echo json_encode(['status' => -1, 'msg' => '邮箱名已被占用请更换!']);
  48. } else {
  49. // 邮箱可用,执行插入操作
  50. $sql = 'INSERT user SET name=:name,email=:email,password=md5(:password1)';
  51. $stmt = $pdo->prepare($sql);
  52. if ($stmt->execute($_POST)) {
  53. if ($stmt->rowCount()==1) {
  54. // 实现注册后自动登录
  55. $_SESSION['email'] = $_POST['email'];
  56. echo json_encode(['status' => 1, 'msg' => '注册成功,自动登录中...']);
  57. } else {
  58. echo json_encode(['status' => 1, 'msg' => '注册异常,请联系管理员!']);
  59. }
  60. } else {
  61. print_r($stmt->errorInfo());
  62. }
  63. }
  64. break;
  65. // 退出登录
  66. case 'logout':
  67. // 1.清空session变量
  68. session_unset();
  69. // 2.删除session文件
  70. session_destroy();
  71. echo '<script>alert("退出成功");location.href="index.php";</script>';
  72. break;
  73. default:
  74. exit('非法操作');
  75. }
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议