Android 为什么Google ReCaptcha API允许坏密钥和/或坏用户令牌响应?
请看下面的代码。这是服务器端。正如您所看到的,我使用错误的密钥和错误的用户令牌响应调用GoogleRecapTChaAPI。你知道吗?它起作用了!更准确地说:Google ReCaptcha API没有回答异常,即:未达到我的捕获。为什么?这不是预期的行为,对吗Android 为什么Google ReCaptcha API允许坏密钥和/或坏用户令牌响应?,android,google-cloud-functions,recaptcha,Android,Google Cloud Functions,Recaptcha,请看下面的代码。这是服务器端。正如您所看到的,我使用错误的密钥和错误的用户令牌响应调用GoogleRecapTChaAPI。你知道吗?它起作用了!更准确地说:Google ReCaptcha API没有回答异常,即:未达到我的捕获。为什么?这不是预期的行为,对吗 /** * Verifies a Recaptcha filled by the user in his Android app. * 1. Success: returns the JSON response * 2. Fail
/**
* 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();
}
建议在响应的错误代码字段中出现错误,例如无效输入密码/无效输入响应
此信息不一定需要转换为HTTP错误代码,这将导致执行catch块;在这个例子中,Google显然希望支持多个同时发生的错误消息,而HTTP响应代码更多地涉及HTTP级别的协议执行
当我们查看文档时,我应该指出,在假定您的用户是人类之前,您可能希望参考成功字段。因此,您建议我,如果写入了错误的密钥(例如),不要向Android应用程序发送HTTP错误?是的,谢谢,我已经写了,但是忘了在OPI中指出。如果我是你,我会抛出一个无效的输入密码,让客户端知道服务器有问题。同时,您可能还应该在内部记录该事件,并让服务器向站点管理员发送电子邮件,让他们知道该问题。因为如果您自己的服务器发送了错误的机密,那么您需要知道这一点。但是如果你得到一个无效的输入响应,这取决于你;您可以假定客户端出现故障,也可以假定客户端是恶意的。不管怎样,你都可能不允许访问。如果我返回这个JSON对象而不是抛出一个异常,那么它是好还是坏。然后parsedBody=>{if!parsedBody.success{return{code:-1};}return{code:0};}嗯,这主要是口味的问题。对于您的框架来说,最适合/最优雅的;无论你的客户理解什么。如果你不想,你不必告诉客户他不是人类;合法的recaptchas除非通过,否则不会生成userResponseToken,所以发送一个非法的是一种非常激进的黑客行为,IMHO。。。