javascript - 如何使用“标头已发送”常见错误(gCaptcha + 重定向)在 php 中重定向
问题描述
运行我的脚本时,我在调用 header() 时遇到这样的错误。我知道已经有答案(如何修复 PHP 中的“标头已发送”错误)但我不明白,在尝试了所有解决方案之后,只有 java 解决方案有效,这是一个非常糟糕的解决方案。如果没有 gCaptcha 部分(只有表单),我的代码正在工作,没有表单(只有 gCaptcha)我的代码也可以工作,但是如果组合代码不起作用......
对于每个 header() 调用,我的错误都是这样的:
“警告:无法修改标头信息 - 标头已由 C:\wamp64 中的(输出开始于 C:\wamp64\www\Travail\WebApp1\login.php:126)发送\www\Travail\WebApp1\login.php 在第 251 行"
我需要改变什么?老实说,我已经阅读了有关此问题的所有问题,但 8 小时后,我仍然无法通过真正的解决方案解决问题。
我的整个代码:
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
session_start();
require_once "config.php";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
<title>Login</title>
</head>
<body>
<nav class="navbar navbar-dark bg-primary">
<div class="container-fluid">
<a class="navbar-brand" href="index.php">My Web App</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="signup.php">Sign Up</a>
</li>
<li class="nav-item">
<a class="nav-link" href="login.php">Login</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Admin</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="login-form">
<?php
if(isset($_GET['login_err']))
{
$err = htmlspecialchars($_GET['login_err']);
switch($err)
{
case 'password':
?>
<div class="alert alert-danger">
<strong>Error</strong> wrong password
</div>
<?php
break;
case 'email':
?>
<div class="alert alert-danger">
<strong>Error</strong> invalid email
</div>
<?php
break;
case 'already':
?>
<div class="alert alert-danger">
<strong>Error</strong>Please enter valide information
</div>
<?php
}
}
?>
<form method="post" id="demo-form">
<h2 class="text-center">Login</h2>
<input type="hidden" id="g-token" name="g-token" />
<div class="form-group">
<input type="email" name="email" class="form-control" placeholder="Email" required="required" autocomplete="on">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" placeholder="password" required="required" autocomplete="off">
</div>
<div class="form-group">
<button type="submit" name="btnSubmit" class=" btn btn-primary btn-block" style=" margin-left: 35% ;" >Login</button>
</div>
<div class="form-group">
<a href="forgot.php" style="margin-left:25%;"> Forgot password ? </a>
</div>
</form>
</div>
<style>
.login-form {
width: 340px;
margin: 50px auto;
}
.login-form form {
margin-bottom: 15px;
background: #f7f7f7;
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
padding: 30px;
}
.form-group {
margin-top: 1em;;
}
.login-form h2 {
margin: 0 0 15px;
}
.form-control, .btn {
min-height: 38px;
border-radius: 2px;
}
.btn {
font-size: 15px;
font-weight: bold;
}
</style>
<!-- Google Captcha Scripts -->
<script src="https://www.google.com/recaptcha/api.js?render=6LcOd1cbAAAAAOiqthb4pwaH0vfrVDyB89D6q4V8"></script>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('6LcOd1cbAAAAAOiqthb4pwaH0vfrVDyB89D6q4V8', {action: 'homepage'}).then(function(token) {
console.log(token);
document.getElementById("g-token").value = token;
});
});
</script>
<!-- Optional JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script>
</body>
</html>
<?php
if(!empty($_POST["g-token"]) && !empty($_POST['email']) && !empty($_POST['password']))
{
$secretKey = '6LcOd1cbAAAAALaDm52utDpT2bt6DNtMNNivW-9s';
$token = $_POST["g-token"];
$ip = $_SERVER['REMOTE_ADDR'];
/* ======================= POST METHOD =====================*/
$url = "https://www.google.com/recaptcha/api/siteverify?";
$data = array('secret' => $secretKey, 'response' => $token, 'remoteip'=> $ip);
// use key 'http' even if you send the request to https://...
$options = array('http' => array(
'method' => 'POST',
'content' => http_build_query($data),
'header' => 'Content-Type: application/x-www-form-urlencoded'
));
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$response = json_decode($result);
if($response->success)
{
echo '<center><h1>Validation Success!</h1></center>';
}
else
{
echo '<center><h1>Captcha Validation Failed..!</h1></center>';
}
//Avoid XSS
$email = htmlspecialchars($_POST['email']);
$password = htmlspecialchars(($_POST['password']));
$email = strtolower($email);
echo $email;
echo $password;
$check = $bdd->prepare('SELECT * FROM users WHERE email = ?');
$check->execute(array($email));
$data = $check->fetch();
$row = $check->rowCount();
echo $row;
if($row > 0)
{
if(filter_var($email, FILTER_VALIDATE_EMAIL))
{
if(password_verify($password, $data['password']))
{
$_SESSION['user'] = $data['token'];
//echo "<script type='text/javascript'>window.top.location='app.php';</script>"; exit;
header('Location: index.php');
die();
}else{echo "<script type='text/javascript'>window.top.location='login.php?login_err=password';</script>"; exit;
//header('Location: login.php?login_err=password'); die();
}
}else{echo "<script type='text/javascript'>window.top.location='login.php?login_err=email';</script>"; exit; }
}else{ echo "<script type='text/javascript'>window.top.location='login.php?login_err=already';</script>"; exit; }
}
else{ die();}
?>
如果我替换“header('Location: index.php');” BY“回声”window.top.location='app.php';“;退出;” 它有效,但它不是一个真正的解决方案。
顺便说一句,为了显示错误,我的前 3 行代码是否正确?(我正在使用 localhost wamp 运行代码)
解决方案
在将任何其他输出发送到页面之前,必须调用 header() 函数。因此,在您的情况下,您可能希望在输出 HTML 之前将页面底部的 PHP 代码表单处理块移动到顶部。请注意,这意味着您还需要将这些验证响应字符串分配给变量,并在适当的情况下在页面中进一步回显它们。
推荐阅读
- azure-devops - 如何在`.vsts-ci.yml`中的VSTS CI上以小写设置变量名?
- reactjs - 为什么这不适用于 recompose 和 ramda?
- html - 如何缩放高度数字微调器(输入类型 =“数字”)
- android - SQLite插入具有相同值的多行
- sql-server - 如何获得 H12_LC、F12_LC、Sales_LC 列的总和?
- dialogflow-es - Dialogflow 提供对意图有效的特定选项
- aurelia - IdentityServer 的 Aurelia 和 Open-Id-Connect 插件
- jquery - 获取 div 容器中的最大值
- c++ - 通过指针调用模板类成员函数[为什么这是有效的 c++]?
- c - 未定义对“powerOfThree”的引用