我正在开发基于php和angular 6的单页应用程序。
除今天在控制台上看到以下错误外,该项目正常运行:
从“ http://dev.local/scripts/login.php”访问XMLHttpRequest 原产地“ http://localhost:4200”已被CORS政策禁止: 'Access-Control-Allow-Origin'标头包含多个值 'http://localhost:4200,*',但只允许一个。
dev.local
是指使用wampserver创建的用于测试目的的虚拟主机。
在login.php上,我具有以下脚本:
PHP 调用脚本:
<?php
require_once('../api.php');
//Getting username and password from Angular
$user = $_POST['username'];
$password = $_POST['password'];
$newApi = new api();
$conn = $newApi->connection();
//var_dump($conn);
$res = $newApi->login($conn, $user, $password);
echo json_encode($res);
?>
在API上:
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: *');
header('Content-Type: application/json');
header('Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS');
header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
error_reporting(E_ALL);
require_once('JWT.php');
include_once('../phpmailer/PHPMailer.php');
include_once('../phpmailer/POP3.php');
include_once('../phpmailer/SMTP.php');
include_once('../phpmailer/Exception.php');
class api {
private $username ="root";
private $password ="root";
private $db="reg_sys";
private $host = "localhost";
public $conn;
public $key = "key123";
public $sessionJwt;
public function connection(){
session_start();
try{
$this->conn = new PDO("mysql:host=$this->host;dbname=$this->db", $this->username, $this->password);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->conn->exec("SET CHARACTER SET utf8");
return $this->conn;
}
catch(PDOException $e){
return $e->getMessage();
}
}
public function login($conn, $user, $password){
try{
$exist = $this->checkIfUserExist($conn, $user);
if($exist['exist'])
{
//Check Password and Generate a token
$checkPassword = "SELECT user_id, user_name, user.role_id, roles.role_type
FROM user
LEFT JOIN roles ON user.role_id = roles.role_id
WHERE
user_name = :user
AND
user_password = :pass
LIMIT 1";
$execCheckPassword = $this->conn->prepare($checkPassword);
$execCheckPassword->bindValue('user', $user);
$execCheckPassword->bindValue('pass', $password);
$execCheckPassword->execute();
$fetchRes = $execCheckPassword->fetch();
$resFound = $execCheckPassword->rowCount();
//Then
if($resFound>0)
{
//Generate a JWT
//Array to generate a JWT from
$arrayJWT =
[
'login_id'=>$fetchRes['user_id'],
'username'=> $fetchRes['user_name'],
'user_role'=>$fetchRes['role_type']
];
$encodedJWT = JWT::encode($arrayJWT, $this->key);
$resArray =
[
'jwt'=> $encodedJWT,
'user_exist'=> 'true',
'user_id'=>$fetchRes['user_id'],
'username'=> $fetchRes['user_name'],
'user_role'=>$fetchRes['role_type']
];
$_SESSION['jwt']=$encodedJWT;
}
else
{
$resArray = ['user_exist'=> 'false', 'errorMsg' => "Incorrect Password!!!"];
//Insert into login_attempt table
$sql = "INSERT INTO login_attempt(login_attempt_date, login_attempt_status, user_id)
VALUES(:date_time, :attempt_status, :user_id)";
$exec = $conn->prepare($sql);
$exec->bindValue(':date_time', $this->currentDateTime);
$exec->bindValue(':attempt_status', 'Active');
$exec->bindValue(':user_id', $exist['user_id']);
$exec->execute();
}
}
else
{
$resArray = ['user_exist'=> 'false', 'errorMsg' => "Username doesn't exist"];
}
return $resArray;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
}
在斜边:
login(username, password): Observable<any> {
let headerOptions = new HttpHeaders();
//headerOptions.append('Access-Control-Allow-Origin', '*');
//headerOptions.append('Access-Control-Request-Headers', '*');
headerOptions.append('Access-Control-Allow-Credentials', 'true');
headerOptions.append('Content-Type', 'application/json');
headerOptions.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH,OPTIONS');
headerOptions.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
this.credentials = { user: username, pass: password };
const httpParams = new HttpParams()
.set('username', username)
.set('password', password);
return this.http.post(this.globalVar.login, httpParams, {
headers: headerOptions,
})
}
如您所见,我评论了以下内容:
//headerOptions.append('Access-Control-Allow-Origin', '*');
//headerOptions.append('Access-Control-Request-Headers', '*');
在httpd-vhosts.conf上:
# Virtual Hosts
#
<VirtualHost *:80>
ServerName localhost
ServerAlias localhost
DocumentRoot "${INSTALL_DIR}/www"
<Directory "${INSTALL_DIR}/www/">
Options +Indexes +Includes +FollowSymLinks +MultiViews
Header set Access-Control-Allow-Origin "*"
AllowOverride All
Require local
Allow from 127.0.0.1
Allow from 192.168.10.0
Allow from 192.168.0.217
Require all granted
</Directory>
</VirtualHost>
#dev.local
<VirtualHost *:80>
ServerAdmin it@m.org
DocumentRoot "c:/wamp64/www/dev"
ServerName dev.local
ServerAlias www.dev.local
<Directory "c:/wamp64/www/dev/">
AllowOverride All
Require local
Allow from 127.0.0.1
#Allow from 192.168.10.0
#Allow from 192.168.0.140
Require ip 192.168.0
Require ip 192.168.1
Require ip 192.168.10
Require all granted
Allow from all
</Directory>
</VirtualHost>
然后我在httpd.conf
中启用了mod_headers。
我从堆栈上的这个question和这个answer尝试了解决方案,但是什么都没有改变,仍然遇到相同的错误。
XHRResponse:
fetch(“ http://dev.local/scripts/login.php”, {“ credentials”:“ omit”,“ headers”:{“ accept”:“ application / json, 文字/纯文字, / “,”内容类型“:” application / x-www-form-urlencoded; charset = UTF-8“},” referrer“:” http://localhost:4200/login“,” referrerPolicy“ :“降级时无推荐人”,“正文”:“ username = test&password = test1”,“ method”:“ POST”,“ mode”:“ cors”});
答案 0 :(得分:2)
在使用后端进行开发时,我已经多次面对这个问题。在服务器上,托管应用程序时,可以使用服务中的URL作为\login
而不是http://localhost:8000/login
来使用相同的域。
对于本地开发,请使用proxy config运行angular dev服务器。请阅读https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md。这会将/login
的来源从http://localhost:4200
更改为http://localhost:8000
。
更新:(localhost:8000只是一个示例,您的可能会有所不同) 事实是,浏览器不允许来自混合源(HTTP和HTTPS的混合)和跨源(来自XHR的不同源的数据)的内容。因此使用代理来欺骗浏览器。
您的应用程序将\login
发送到localhost:4200
,并且由于\login
API,您的角度配置服务器中的代理配置将所有流量路由到localhost:8000
到\login
居住在那里。但是浏览器将看到您正在向localhost:4200\login
发送请求,因此不会再发生CORS问题。您的角度开发服务器将负责路由您的后端API。您只需要添加相同的配置即可。
如果您不理解,请随时提出更多疑问。将尝试另一种方法进行解释。
希望这对您有所帮助。这将消除CORS的问题。