我正在使用Devise和CanCanCan来管理用户身份验证和授权,但由于某种原因,我的current_user对象始终是nil Rails端,即使我使用我的登录获得成功消息。我不确定断开连接是什么,但在成功登录后我无法检索任何资源。
我正在寻找的是,我想更好地了解幕后发生的事情。一旦用户登录,我就会从rails侧发回X-CSRF-Token标头(form_authenticity_token),但我的理解是,这只需要从我的iOS应用程序传回服务器以获取写入服务器(POST,PUT,DELETE)。如果是这种情况,那么如何向服务器标识自己的GET请求?
答案 0 :(得分:2)
经过一番研究,我就是如何总结我最终做的事情。
对于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];
}
我在会话控制器中执行了以下操作:
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。但是,我跳过了创建的真实性验证。这意味着虽然创建会话本身并不需要真实性令牌,但是一旦操作完成,它将向请求者发送一个令牌,这样请求者就可以在将来的所有写操作中使用该令牌。
如果我遗漏了某些内容或做错了什么,请告诉我,我会更新此答案。