为什么 Google ReCaptcha API 允许错误的密钥 and/or 错误的用户令牌响应?
Why does Google ReCaptcha API allow bad secret key and/or bad user token response?
看看下面的代码。这是服务器端。如您所见,我用错误的密钥和错误的用户令牌响应调用 Google ReCaptcha API。你知道吗?有用!更准确地说:Google ReCaptcha API 没有异常回答( 即: 我的 catch
未达到)。为什么?这不是预期的行为,对吗?
/**
* Verifies a Recaptcha filled by the user in his Android app.
* 1. Success: returns the JSON response
* 2. Failure: throws the error
**/
exports.verifyRecaptcha = functions.https.onCall((data, context) => {
const user_response_token = data.userResponseToken;
if(user_response_token === null || user_response_token === '') {
throw new functions.https.HttpsError('invalid-argument', 'The function must be called with an adequat user response token.');
}
const remote_url = 'https://recaptcha.google.com/recaptcha/api/siteverify';
const secret = '<MY_REAL_SECRET_KEY>'; // Original value: 'https://www.google.com/recaptcha/api/siteverify'; # Moises' value: https://recaptcha.google.com/recaptcha/api/siteverify
var options = {
method: 'POST',
uri: remote_url,
body: {secret: 'Foo', response: 'Bar'},
// body: {secret: secret, response: user_response_token},
json: true
};
return rp(options)
.then(parsedBody => {
return {code: 'Success', message: 'You are actually a human (this msg is for test purposes).'};
})
.catch(error => {
throw new functions.https.HttpsError('unknown', error);
});
});
下面是 Android 应用程序代码:
final SafetyNetApi.RecaptchaTokenResponse response = task.getResult();
assert response != null;
final String userResponseToken = response.getTokenResult();
if (!userResponseToken.isEmpty()) {
final HashMap<String, String> the_data = new HashMap<>();
the_data.put("userResponseToken", userResponseToken);
FirebaseFunctions.getInstance()
.getHttpsCallable("verifyRecaptcha")
.call(the_data)
.continueWith(new Continuation<HttpsCallableResult, Void>() {
@Override
public Void then(@NonNull final Task<HttpsCallableResult> task) {
if(context.isDestroyed() || context.isFinishing()) {
return null;
}
if(!task.isSuccessful()) {
Exception e = task.getException();
if (e instanceof FirebaseFunctionsException) {
FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
System.out.println(ffe.getMessage());
}
return null;
}
callback.onAsking();
return null;
}
});
} else {
callback.onFailureUserResponseTokenIsEmpty();
}
docs提示invalid-input-secret
/invalid-input-response
等错误会出现在响应的error-codes
字段中。
此信息不一定需要转换为 HTTP 错误代码(这会导致您的 catch
块执行);在这种情况下,Google 显然想要支持多个同时出现的错误消息,并且 HTTP 响应代码更多地与协议在 HTTP 级别的行为有关。
在我们查看文档时,我应该指出,在假定您的用户是人类之前,您可能想参考 success
字段。
看看下面的代码。这是服务器端。如您所见,我用错误的密钥和错误的用户令牌响应调用 Google ReCaptcha API。你知道吗?有用!更准确地说:Google ReCaptcha API 没有异常回答( 即: 我的 catch
未达到)。为什么?这不是预期的行为,对吗?
/**
* Verifies a Recaptcha filled by the user in his Android app.
* 1. Success: returns the JSON response
* 2. Failure: throws the error
**/
exports.verifyRecaptcha = functions.https.onCall((data, context) => {
const user_response_token = data.userResponseToken;
if(user_response_token === null || user_response_token === '') {
throw new functions.https.HttpsError('invalid-argument', 'The function must be called with an adequat user response token.');
}
const remote_url = 'https://recaptcha.google.com/recaptcha/api/siteverify';
const secret = '<MY_REAL_SECRET_KEY>'; // Original value: 'https://www.google.com/recaptcha/api/siteverify'; # Moises' value: https://recaptcha.google.com/recaptcha/api/siteverify
var options = {
method: 'POST',
uri: remote_url,
body: {secret: 'Foo', response: 'Bar'},
// body: {secret: secret, response: user_response_token},
json: true
};
return rp(options)
.then(parsedBody => {
return {code: 'Success', message: 'You are actually a human (this msg is for test purposes).'};
})
.catch(error => {
throw new functions.https.HttpsError('unknown', error);
});
});
下面是 Android 应用程序代码:
final SafetyNetApi.RecaptchaTokenResponse response = task.getResult();
assert response != null;
final String userResponseToken = response.getTokenResult();
if (!userResponseToken.isEmpty()) {
final HashMap<String, String> the_data = new HashMap<>();
the_data.put("userResponseToken", userResponseToken);
FirebaseFunctions.getInstance()
.getHttpsCallable("verifyRecaptcha")
.call(the_data)
.continueWith(new Continuation<HttpsCallableResult, Void>() {
@Override
public Void then(@NonNull final Task<HttpsCallableResult> task) {
if(context.isDestroyed() || context.isFinishing()) {
return null;
}
if(!task.isSuccessful()) {
Exception e = task.getException();
if (e instanceof FirebaseFunctionsException) {
FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
System.out.println(ffe.getMessage());
}
return null;
}
callback.onAsking();
return null;
}
});
} else {
callback.onFailureUserResponseTokenIsEmpty();
}
docs提示invalid-input-secret
/invalid-input-response
等错误会出现在响应的error-codes
字段中。
此信息不一定需要转换为 HTTP 错误代码(这会导致您的 catch
块执行);在这种情况下,Google 显然想要支持多个同时出现的错误消息,并且 HTTP 响应代码更多地与协议在 HTTP 级别的行为有关。
在我们查看文档时,我应该指出,在假定您的用户是人类之前,您可能想参考 success
字段。