Вот что я обнаружил.Проблема связана с тем, что параметр GET диктует что-либо об объекте, выбранном в Salesforce, а затем сохраняет данные в этом объекте.Я не верю, что когда-либо существовала реальная проблема безопасности, и с моим новым кодом тест безопасности прошел без проблем.По сути, это происходит так:
String token = ApexPages.currentPage().getParameters().get('oauth_token');
CustomObject__c pcs = [
SELECT Id, User__c, Token__c
FROM CustomObject__c
WHERE Id = :UserInfo.getUserId()
AND Token__c = :EncodingUtil.urlEncode(token, 'UTF-8'];
Поскольку весь этот обмен начинается с моего контекста, где я на 100% уверен в текущем пользователе (UserInfo.getUserId ()), мне не нужнопроверьте, совпадает ли этот конкретный токен, так как пользователь гарантирован (по крайней мере, в связи со мной, инициирующим этот процесс).Таким образом, следующий выбор отлично работает:
CustomObject__c pcs = [
SELECT Id, User__c, Token__c
FROM CustomObject__c
WHERE Id = :UserInfo.getUserId()];
Затем, если я обновлю этот объект:
update pcs;
, он не будет жаловаться, так как переданное значение GET неиметь какую-либо связь с объектом, выбранным для записи.Однако, как вы могли заметить, проблем на самом деле никогда не было - до тех пор, пока я включил
WHERE Id = :UserInfo.getUserId()
в оператор SOQL.Причина в том, что независимо от того, какие фальшивые токены пыталась внедрить атака в мой код, он все равно проверялся против текущего пользователя и в любом случае потерпел бы неудачу, если пользователь не совпадал.Но в Salesforce нет никакого способа, позволяющего одновременно войти в систему двум пользователям, как в большинстве систем, поэтому проверка токенов с самого начала была излишней, поскольку я никогда не делюсь своими идентификаторами пользователей с Twitter.
Токены фактические , которые необходимо сохранить (oauth_token и oauth_secret), могут быть получены как параметры POST и, следовательно, имеют встроенную защиту Salesforce CSRF.Они получены следующим образом:
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setEndpoint(accessTokenURL);
req.setBody('');
sign(req);
HttpResponse res = new HttpResponse();
String resParams = res.getBody();
Map<String,String> rp = new Map<String,String>();
if(resParams != null)
{
for(String s : resParams.split('&'))
{
List<String> kv = s.split('=');
rp.put(kv[0],kv[1]);
}
}
tK.Secret__c = rp.get('oauth_token_secret');
tK.Token__c = rp.get('oauth_token');
upsert tK; // No problem, it's from a POST body
И я собирался ПОСТАВИТЬ щедрость;)