- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
请原谅我的笨拙,我是 Stackoverflow、C# 和 Objective C 的新手。
简而言之,我正在尝试做这个问题的答案,但在 PHP 中: How to authenticate the GKLocalPlayer on my 'third party server'?希望这也能帮助其他从事相同工作的 PHP 开发人员。
我正在使用 Unity (Unity3D) 和 PHP 服务器端。我已经让 Objective C 正确连接到 GameCenter 并通过调用 generateIdentityVerificationSignatureWithCompletionHandler
返回数据。不幸的是,我无法弄清楚我在验证 SHA1 哈希时做错了什么。过去一周我一直在研究这个问题,尝试了各种方法,但没有成功。
我正在尝试三种不同的方法来制作 SHA1 哈希(如下所示)。一次在 Objective C 中,另一个在 Unity 的 C# 中,最后第三次在我的服务器上用 PHP。 Objective C 和 C# SHA1 哈希值最终相同。但是,PHP 不匹配它们。并且没有人根据 Apple 的公共(public)证书和签名进行验证。
不可否认,我可能误解了一些基本的东西。至少让 Objective C 和 C# 哈希得到验证将是一个巨大的进步。
谢谢。
objective-c 代码:
[localPlayer generateIdentityVerificationSignatureWithCompletionHandler:^(NSURL *publicKeyUrl, NSData *signature, NSData *salt, uint64_t timestamp, NSError *error) {
NSDictionary *params = @{@"public_key_url": [publicKeyUrl absoluteString],
@"timestamp": [NSString stringWithFormat:@"%llu", timestamp],
@"signature": [signature base64EncodedStringWithOptions:0],
@"salt": [salt base64EncodedStringWithOptions:0],
@"player_id": [GKLocalPlayer localPlayer].playerID,
@"app_bundle_id": [[NSBundle mainBundle] bundleIdentifier]};
// Build hash using iOS...
NSMutableData *payload = [[NSMutableData alloc] init];
[payload appendData:[[GKLocalPlayer localPlayer].playerID dataUsingEncoding:NSASCIIStringEncoding]];
[payload appendData:[[[NSBundle mainBundle] bundleIdentifier] dataUsingEncoding:NSASCIIStringEncoding]];
uint64_t timestampBE = CFSwapInt64HostToBig(timestamp);
[payload appendBytes:×tampBE length:sizeof(timestampBE)];
[payload appendData:salt];
uint8_t sha1HashDigest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1([payload bytes], [payload length], sha1HashDigest);
// Convert to hex string so it can be sent to Unity's C# then to the PHP webserver...
NSString *sIOSHash = [self stringFromDigest:sha1HashDigest length:CC_SHA1_DIGEST_LENGTH];
// END - Build hash using iOS
// Build string to send to Unity's C#...
NSMutableString * data = [[NSMutableString alloc] init];
[data appendString:params[@"public_key_url"]];
[data appendString:@","];
[data appendString:params[@"timestamp"]];
[data appendString:@","];
[data appendString:params[@"signature"]];
[data appendString:@","];
[data appendString:params[@"salt"]];
[data appendString:@","];
[data appendString:params[@"player_id"]];
[data appendString:@","];
[data appendString:params[@"app_bundle_id"]];
[data appendString:@","];
[data appendString:sIOSHash];
// END - Build string to send to Unity's C#.
// Send string to Unity's C# for parsing and sending off to PHP webserver.
NSString *str = [[data copy] autorelease];
UnitySendMessage("GameCenterManager", "onAuthenticateLocalPlayer", [ISNDataConvertor NSStringToChar:str]);
}];
// Helper method to convert uint8_t into a hex string for sending to the webserver.
- (NSString *)stringFromDigest:(uint8_t *)digest length:(int)length {
NSMutableString *ms = [[NSMutableString alloc] initWithCapacity:length * 2];
for (int i = 0; i < length; i++) {
[ms appendFormat: @"%02x", (int)digest[i]];
}
return [ms copy];
}
接下来是用于生成第二个版本的 SHA1 哈希的 C# 代码(在 Unity3D 中)。这些变量都从 iOS 代码(上面)发送到 Unity,并以字符串形式传入:player_id
、app_bundle_id
、timestamp
、盐
。(我没有显示任何要发送到我的服务器的 Unity3D C# 代码。但我正在使用 WWWForm
和 AddField
发送它。我也没有显示“桥"将数据从 Objective C 移动到 C# 的代码。)
var sha1 = new SHA1Managed();
var data = new List<byte>();
data.AddRange(Encoding.UTF8.GetBytes(player_id));
data.AddRange(Encoding.UTF8.GetBytes(app_bundle_id));
data.AddRange(ToBigEndian(Convert.ToUInt64(timestamp)));
data.AddRange(Convert.FromBase64String(salt));
var sig = data.ToArray();
public static string CSharpHash = ToHex(sha1.ComputeHash(sig), false);
最后一个代码块是我的服务器端 PHP,它从客户端接收数据,验证公共(public)证书,然后尝试根据它和签名验证哈希。最后一部分是我卡住的地方。
/*
Sample data as received within the PHP (all strings):
$public_cert_url eg: https://sandbox.gc.apple.com/public-key/gc-sb.cer
$timestamp eg: 00-00-01-47-12-9C-16-D4 [derived from: 1404766525140]
$signature eg: EGc8J9D7SdZ0qq2xl2XLz2[lots more...]
$salt eg: LDfyIQ==
$player_id eg: G:[#########]
$app_bundle_id eg: com.[mydomain].[myapp]
$sIOSHash eg: 00032b9416315c8298b5a6e7f5d9dec71bd5ace2 [The C# and Objective C code both generate the same hash.]
$CSharpHash eg: 00032b9416315c8298b5a6e7f5d9dec71bd5ace2
*/
// Verify the public cert.
// As far as I understand, PHP's openssl_pkey_get_public() cannot read raw
// cer data, so I download and convert to PEM. Optimize later.
$fp = fopen("temp.cer", "w"); // Open file for writing.
$header[] = "Content-Type: application/pkix-cert";
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_URL, $public_cert_url);
curl_setopt($curl, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FILE, $fp);
curl_exec($curl);
curl_close($curl);
fclose($fp);
shell_exec("openssl x509 -inform der -in temp.cer -out temp.pem"); // Convert to PEM.
$pub_cert = file_get_contents("temp.pem");
$sKey = openssl_pkey_get_public($pub_cert); // Validate PEM file here.
If( $sKey === False ) echo "pkey bad";
// This ^^ works.
// This is where I am stuck:
// Verify the data from the client against the signature from the client
// and the downloaded public key.
// First, try to verify against a hash created within PHP:
$iResult = openssl_verify(
sha1($player_id . $app_bundle_id . $timestamp . $salt),
$signature,
$pub_cert,
OPENSSL_ALGO_SHA1);
If( $iResult != 1 ) echo "not valid PHP hash!\n";
// Second, see if it will verify by using the hash created in.
$iResult = openssl_verify($sIOSHash, $signature, $pub_cert, OPENSSL_ALGO_SHA1);
If( $iResult != 1 ) echo "not valid sIOSHash hash!\n";
// Finally, does the C# has verify?
$iResult = openssl_verify($CSharpHash, $signature, $pub_cert, OPENSSL_ALGO_SHA1);
If( $iResult != 1 ) echo "not valid CSharpHash hash!\n";
// None of these ^^ ever validate.
更新:2014 年 7 月 9 日
我通过不对其执行 SHA1 来验证数据。我对 Apple 文档感到困惑(https://developer.apple.com/library/prerelease/ios/documentation/GameKit/Reference/GKLocalPlayer_Ref/index.html#//apple_ref/occ/instm/GKLocalPlayer/generateIdentityVerificationSignatureWithCompletionHandler :)。特别是#7,它说:“为缓冲区生成一个 SHA-1 哈希值。”
我删除了所有 C# 代码(以尝试生成有效载荷),现在只使用 Objective C。
修改如下:
NSMutableData *payload = [[NSMutableData alloc] init];
[payload appendData:[[GKLocalPlayer localPlayer].playerID dataUsingEncoding:NSUTF8StringEncoding]];
[payload appendData:[[[NSBundle mainBundle] bundleIdentifier] dataUsingEncoding:NSUTF8StringEncoding]];
uint64_t timestampBE = CFSwapInt64HostToBig(timestamp);
[payload appendBytes:×tampBE length:sizeof(timestampBE)];
[payload appendData:salt];
NSString *siOSData = [payload base64EncodedStringWithOptions:0];
注意 SHA1 的删除。
我放弃了用 PHP 创建负载的尝试。我尝试了许多不同的包、转换、将我的服务器升级到 64 位等。但我认为(如果我错了请纠正我)因为我从客户端传输与构成有效载荷完全相同的数据,它应该没关系。
Apple 注意事项:
请实现 OAuth 2.0。
我还想出了如何验证 Apple cer 文件而不浪费处理保存到文件的方法。如下:
// Get data from client. I urlencoded it before sending. So need to urldecode now.
// The payload is in "iosdata" and it, along with the signature, both need to be
// base64_decoded.
$sIOSData = ( isset($_REQUEST["iosdata"]) ) ? urldecode(Trim($_REQUEST["iosdata"])) : "";
$sIOSData = base64_decode($sIOSData);
$sSignature = ( isset($_REQUEST["signature"]) ) ? urldecode(Trim($_REQUEST["signature"])) : "";
$sSignature = base64_decode($sSignature);
// Here is where I download Apple's cert (DER format), save it as raw bits
// to a variable, convert it to PEM format (the ONLY format PHP's OpenSSL
// works with apparently...?) and then validate it.
// TODO: figure out if Apple live returns different results each time, and/or if
// this can be cached. Apple sandbox returns the same each time.
$header[0] = "Content-Type: application/pkix-cert";
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_URL, $sPublicKeyUrl);
curl_setopt($curl, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$der_data = curl_exec($curl);
curl_close($curl);
$sPublicKey = chunk_split(base64_encode($der_data), 64, "\n");
$sPublicKey = "-----BEGIN CERTIFICATE-----\n".$sPublicKey."-----END CERTIFICATE-----\n";
$sKey = openssl_pkey_get_public($sPublicKey);
If( $sKey === False ) Return "pkey bad";
// Here I use the package ($sIOSData) and signature to validate against Apple's
// public certificate.
$iResult = openssl_verify($sIOSData, $sSignature, $sKey, OPENSSL_ALGO_SHA1);
If( $iResult != 1 ) {
echo "BAD!\n";
echo "error: ".openssl_error_string()."\n";
}else{
echo "WORKED!\n";
}
欢迎反馈。我敢肯定有很多事情可以改进。但希望这会帮助某人节省一周的工作时间。
最佳答案
我玩得很开心。 Garraeth 的代码很有帮助,但 SO 周围散布着一些其他有用的提示,加上 php 文档,再加上一些幸运的猜测,我终于得出了这个结论:
在 iOS 端:
主要验证用户代码:
// Don't bother verifying not-authenticated players
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
if (localPlayer.authenticated)
{
// __weak copy for use within code-block
__weak GKLocalPlayer *useLocalPlayer = localPlayer;
[useLocalPlayer generateIdentityVerificationSignatureWithCompletionHandler: ^(NSURL * _Nullable publicKeyUrl,
NSData * _Nullable signature,
NSData * _Nullable salt,
uint64_t timestamp,
NSError * _Nullable error) {
if (error == nil)
{
[self verifyPlayer: useLocalPlayer.playerID // our verify routine: below
publicKeyUrl: publicKeyUrl
signature: signature
salt: salt
timestamp: timestamp];
}
else
{
// GameCenter returned an error; deal with it here.
}
}];
}
else
{
// User is not authenticated; it makes no sense to try to verify them.
}
我的 verifyPlayer: 例程:
-(void)verifyPlayer: (NSString*) playerID
publicKeyUrl: (NSURL*) publicKeyUrl
signature: (NSData*) signature
salt: (NSData*) salt
timestamp: (uint64_t) timestamp
{
NSDictionary *paramsDict = @{ @"publicKeyUrl": [publicKeyUrl absoluteString],
@"timestamp" : [NSString stringWithFormat: @"%llu", timestamp],
@"signature" : [signature base64EncodedStringWithOptions: 0],
@"salt" : [salt base64EncodedStringWithOptions: 0],
@"playerID" : playerID,
@"bundleID" : [[NSBundle mainBundle] bundleIdentifier]
};
// NOTE: A lot of the code below was cribbed from another SO answer for which I have lost the URL.
// FIXME: <When found, insert other-SO-answer URL here>
// build payload
NSMutableData *payload = [NSMutableData new];
[payload appendData: [playerID dataUsingEncoding: NSASCIIStringEncoding]];
[payload appendData: [[[NSBundle mainBundle] bundleIdentifier] dataUsingEncoding: NSASCIIStringEncoding]];
uint64_t timestampBE = CFSwapInt64HostToBig(timestamp);
[payload appendBytes: ×tampBE length: sizeof(timestampBE)];
[payload appendData: salt];
// Verify with server
[self verifyPlayerOnServer: payload withSignature: signature publicKeyURL: publicKeyUrl];
#if 0 // verify locally (for testing)
//get certificate
NSData *certificateData = [NSData dataWithContentsOfURL: publicKeyUrl];
//sign
SecCertificateRef certificateFromFile = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData); // load the certificate
SecPolicyRef secPolicy = SecPolicyCreateBasicX509();
SecTrustRef trust;
OSStatus statusTrust = SecTrustCreateWithCertificates(certificateFromFile, secPolicy, &trust);
if (statusTrust != errSecSuccess)
{
NSLog(@"%s ***** Could not create trust certificate", __PRETTY_FUNCTION__);
return;
}
SecTrustResultType resultType;
OSStatus statusTrustEval = SecTrustEvaluate(trust, &resultType);
if (statusTrustEval != errSecSuccess)
{
NSLog(@"%s ***** Could not evaluate trust", __PRETTY_FUNCTION__);
return;
}
if ((resultType != kSecTrustResultProceed)
&& (resultType != kSecTrustResultRecoverableTrustFailure) )
{
NSLog(@"%s ***** Server can not be trusted", __PRETTY_FUNCTION__);
return;
}
SecKeyRef publicKey = SecTrustCopyPublicKey(trust);
uint8_t sha256HashDigest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256([payload bytes], (CC_LONG)[payload length], sha256HashDigest);
NSLog(@"%s [DEBUG] sha256HashDigest: %@", __PRETTY_FUNCTION__, [NSData dataWithBytes: sha256HashDigest length: CC_SHA256_DIGEST_LENGTH]);
//check to see if its a match
OSStatus verficationResult = SecKeyRawVerify(publicKey, kSecPaddingPKCS1SHA256, sha256HashDigest, CC_SHA256_DIGEST_LENGTH, [signature bytes], [signature length]);
CFRelease(publicKey);
CFRelease(trust);
CFRelease(secPolicy);
CFRelease(certificateFromFile);
if (verficationResult == errSecSuccess)
{
NSLog(@"%s [DEBUG] Verified", __PRETTY_FUNCTION__);
dispatch_async(dispatch_get_main_queue(), ^{
[self updateGameCenterUI];
});
}
else
{
NSLog(@"%s ***** Danger!!!", __PRETTY_FUNCTION__);
}
#endif
}
我将代码传递到服务器的例程(摘自这个问题):
- (void) verifyPlayerOnServer: (NSData*) payload withSignature: signature publicKeyURL: (NSURL*) publicKeyUrl
{
// hint courtesy of: http://stackoverflow.com/questions/24621839/how-to-authenticate-the-gklocalplayer-on-my-third-party-server-using-php
NSDictionary *jsonDict = @{ @"data" : [payload base64EncodedStringWithOptions: 0] };
//NSLog(@"%s [DEBUG] jsonDict: %@", __PRETTY_FUNCTION__, jsonDict);
NSError *error = nil;
NSData *bodyData = [NSJSONSerialization dataWithJSONObject: jsonDict options: 0 error: &error];
if (error != nil)
{
NSLog(@"%s ***** dataWithJson error: %@", __PRETTY_FUNCTION__, error);
}
// To validate at server end:
// http://stackoverflow.com/questions/21570700/how-to-authenticate-game-center-user-from-3rd-party-node-js-server
// NOTE: MFURLConnection is my subclass of NSURLConnection.
// .. this routine just builds an NSMutableURLRequest, then
// .. kicks it off, tracking a tag and calling back to delegate
// .. when the request is complete.
[MFURLConnection connectionWitURL: [self serverURLWithSuffix: @"gameCenter.php"]
headers: @{ @"Content-Type" : @"application/json",
@"Publickeyurl" : [publicKeyUrl absoluteString],
@"Signature" : [signature base64EncodedStringWithOptions: 0],
}
bodyData: bodyData
delegate: self
tag: worfc2_gameCenterVerifyConnection
userInfo: nil];
}
在服务器端:
这个问题和其他问题以及 php 文档和...有些抄袭
$publicKeyURL = filter_var($headers['Publickeyurl'], FILTER_SANITIZE_URL);
$pkURL = urlencode($publicKeyURL);
if (empty($pkURL))
{
$response->addparameters(array('msg' => "no pku"));
$response->addparameters(array("DEBUG-headers" => $headers));
$response->addparameters(array('DEBUG-publicKeyURL' => $publicKeyURL));
$response->addparameters(array('DEBUG-pkURL' => $pkURL));
$response->setStatusCode(400); // bad request
}
else
{
$sslCertificate = file_get_contents($publicKeyURL);
if ($sslCertificate === false)
{
// invalid read
$response->addparameters(array('msg' => "no certificate"));
$response->setStatusCode(400); // bad request
}
else
{
// Example code from http://php.net/manual/en/function.openssl-verify.php
try
{
// According to: http://stackoverflow.com/questions/10944071/parsing-x509-certificate
$pemData = der2pem($sslCertificate);
// fetch public key from certificate and ready it
$pubkeyid = openssl_pkey_get_public($pemData);
if ($pubkeyid === false)
{
$response->addparameters(array('msg' => "public key error"));
$response->setStatusCode(400); // bad request
}
else
{
// According to: http://stackoverflow.com/questions/24621839/how-to-authenticate-the-gklocalplayer-on-my-third-party-server-using-php
// .. we use differently-formatted parameters
$sIOSData = $body['data'];
$sIOSData = base64_decode($sIOSData);
$sSignature = $headers['Signature'];
$sSignature = base64_decode($sSignature);
//$iResult = openssl_verify($sIOSData, $sSignature, $sKey, OPENSSL_ALGO_SHA1);
$dataToUse = $sIOSData;
$signatureToUse = $sSignature;
// state whether signature is okay or not
$ok = openssl_verify($dataToUse, $signatureToUse, $pubkeyid, OPENSSL_ALGO_SHA256);
if ($ok == 1)
{
//* echo "good";
$response->addparameters(array('msg' => "user validated"));
}
elseif ($ok == 0)
{
//* echo "bad";
$response->addparameters(array('msg' => "INVALID USER SIGNATURE"));
$response->addparameters(array("DEBUG-$dataToUse" => $dataToUse));
$response->addparameters(array("DEBUG-$signatureToUse" => $signatureToUse));
$response->addparameters(array("DEBUG-body" => $body));
$response->setStatusCode(401); // unauthorized
}
else
{
//* echo "ugly, error checking signature";
$response->addparameters(array('msg' => "***** ERROR checking signature"));
$response->setStatusCode(500); // server error
}
// free the key from memory
openssl_free_key($pubkeyid);
}
}
catch (Exception $ex)
{
$response->addparameters(array('msg' => "verification error"));
$response->addparameters(array("DEBUG-headers" => $headers));
$response->addparameters(array('DEBUG-Exception' => $ex));
$response->setStatusCode(400); // bad request
}
}
// NODE.js code at http://stackoverflow.com/questions/21570700/how-to-authenticate-game-center-user-from-3rd-party-node-js-server
}
不要忘记方便的实用程序:
function der2pem($der_data)
{
$pem = chunk_split(base64_encode($der_data), 64, "\n");
$pem = "-----BEGIN CERTIFICATE-----\n" . $pem . "-----END CERTIFICATE-----\n";
return $pem;
}
利用所有这些,我终于能够从我的服务器上获得“用户验证”。耶! :)
注意:这种方法似乎很容易被黑客攻击,因为任何人都可以用自己的证书签署任何他们想要的东西,然后将数据、签名和 URL 传递给服务器,然后返回一个“that's一个有效的 GameCenter 登录”这样回答,虽然这段代码在实现 GC 算法的意义上“有效”,但算法本身似乎有缺陷。理想情况下,我们还会检查证书是否来自可信来源。额外的偏执检查它是否是 Apple 的 Game Center 证书也很好。
关于php - 如何使用 PHP 验证我的 'third party server' 上的 GKLocalPlayer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24621839/
我在 JavaScript 文件中运行 PHP,例如...... var = '';). 我需要使用 JavaScript 来扫描字符串中的 PHP 定界符(打开和关闭 PHP 的 )。 我已经知道使
我希望能够做这样的事情: php --determine-oldest-supported-php-version test.php 并得到这个输出: 7.2 也就是说,php 二进制检查 test.
我正在开发一个目前不使用任何框架的大型 php 站点。我的大问题是,随着时间的推移慢慢尝试将框架融入应用程序是否可取,例如在创建的新部件和更新的旧部件中? 比如所有的页面都是直接通过url服务的,有几
下面是我的源代码,我想在同一页面顶部的另一个 php 脚本中使用位于底部 php 脚本的变量 $r1。我需要一个简单的解决方案来解决这个问题。我想在代码中存在的更新查询中使用该变量。 $name)
我正在制作一个网站,根据不同的情况进行大量 PHP 重定向。就像这样...... header("Location: somesite.com/redirectedpage.php"); 为了安全起见
我有一个旧网站,我的 php 标签从 因为短标签已经显示出安全问题,并且在未来的版本中将不被支持。 关于php - 如何避免在 php 文件中写入
我有一个用 PHP 编写的配置文件,如下所示, 所以我想用PHP开发一个接口(interface),它可以编辑文件值,如$WEBPATH , $ACCOUNTPATH和 const值(value)观
我试图制作一个登录页面来学习基本的PHP,首先我希望我的独立PHP文件存储HTML文件的输入(带有表单),但是当我按下按钮时(触发POST到PHP脚本) )我一直收到令人不愉快的错误。 我已经搜索了S
我正在寻找一种让 PHP 以一种形式打印任意数组的方法,我可以将该数组作为赋值包含在我的(测试)代码中。 print_r 产生例如: Array ( [0] => qsr-part:1285 [1]
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: What is the max key size for an array in PHP? 正如标题所说,我想知道
我正在寻找一种让 PHP 以一种形式打印任意数组的方法,我可以将该数组作为赋值包含在我的(测试)代码中。 print_r 产生例如: Array ( [0] => qsr-part:1285 [1]
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
我在 MySQL 数据库中有一个表,其中存储餐厅在每个工作日和时段提供的菜单。 表结构如下: i_type i_name i_cost i_day i_start i_
我有两页。 test1.php 和 test2.php。 我想做的就是在 test1.php 上点击提交,并将 test2.php 显示在 div 中。这实际上工作正常,但我需要向 test2.php
我得到了这个代码。我想通过textarea更新mysql。我在textarea中回显我的MySQL,但我不知道如何更新它,我应该把所有东西都放进去吗,因为_GET模式没有给我任何东西,我也尝试_GET
首先,我是 php 的新手,所以我仍在努力学习。我在 Wordpress 上创建了一个表单,我想将值插入一个表(data_test 表,我已经管理了),然后从 data_test 表中获取所有列(id
我有以下函数可以清理用户或网址的输入: function SanitizeString($var) { $var=stripslashes($var); $va
我有一个 html 页面,它使用 php 文件查询数据库,然后让用户登录,否则拒绝访问。我遇到的问题是它只是重定向到 php 文件的 url,并且从不对发生的事情提供反馈。这是我第一次使用 html、
我有一个页面充满了指向 pdf 的链接,我想跟踪哪些链接被单击。我以为我可以做如下的事情,但遇到了问题: query($sql); if($result){
我正在使用 从外部文本文件加载 HTML/PHP 代码 $f = fopen($filename, "r"); while ($line = fgets($f, 4096)) { print $l
我是一名优秀的程序员,十分优秀!