经过更多研究,这就是我总结我最终所做的事情的方式。
对于 GET 请求,您使用内置于 iOS 网络库中的 cookie 存储。默认情况下,这在 NSURLRequest(和可变变体)类中打开。这几乎就是 GET 所需的全部内容。当然,您必须成功登录才能获取 cookie,并且登录需要 POST。
对于 POST、PUT 和 DELETE,您必须在请求中提供 X-CSRF-Token 作为标头。但是,除了登录请求之外的所有请求都是如此,登录请求需要禁用 X-CSRF-Token 标头要求才能创建会话,但下面会详细介绍。
首先,这是针对设备安装在 iOS 上登录的实现(更改了设备登录路由 <server_url>/users/login.json 而不是默认的 <server_url>/users/sign_in.json):
- (void)loginWithUsername:(NSString*)username
password:(NSString*)password
completionBlock:(void(^)(id response, NSError *error))block
{
NSDictionary *loginDictionary = @{@"user" : @{@"email" : username,
@"password" : password}
};
// Convert dictionary to NSData for POST body
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:loginDictionary
options:0
error:&error];
NSString *postUrlString = [NSString stringWithFormat:@"%@users/login.json",
kApiEndpointURL];
NSMutableURLRequest *request = [NSMutableURLRequest
requestWithURL:[NSURL URLWithString:postUrlString]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:kTimeoutInterval];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-type"];
[request setHTTPBody:data];
// This is the default--here for clarity
[request setHTTPShouldHandleCookies:YES];
NSURLSession *session = [NSURLSession sharedSession];
[[UIApplication sharedApplication] showNetworkActivityIndicator];
NSURLSessionDataTask *dataTask =
[session dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
// Save the token so we can perform POSTs, PUTS, and DELETEs
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*)response;
self.xcsrfToken = httpResp.allHeaderFields[@"X-CSRF-Token"];
[[UIApplication sharedApplication] hideNetworkActivityIndicator];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"%@", json);
dispatch_async(dispatch_get_main_queue(), ^{
if (block) {
block(json, error);
}
});
}];
[dataTask resume];
}
- 在 Rails 方面,您需要有一种无需 X-CSRF-Token 即可创建会话的方法,并且您还需要在用户通过身份验证后传回 X-CSRF-Token 以便将来写入行动会成功。
我在我的会话控制器中使用了以下内容:
class SessionsController < Devise::SessionsController
after_filter :set_csrf_header, only: [:create]
skip_before_filter :verify_authenticity_token, only: [:create]
def set_csrf_header
response.headers['X-CSRF-Token'] = form_authenticity_token
end
end
我的会话控制器中有更多内容,但这显示了相关部分。在创建操作的请求成功后,我发回 X-CSRF-Token。但是,我跳过了创建时的真实性验证。这意味着虽然创建会话本身不需要真实性令牌,但它会在操作完成后将其发送回请求者,以便请求者可以在以后的所有写入操作中使用该令牌。
如果我遗漏了什么或做错了什么,请告诉我,我会更新这个答案。