我正在使用Devise和CanCanCan来管理用户身份验证和授权,但是由于某种原因,即使我通过登录获得成功消息,我的current_user对象也始终在Rails方面无效。我不确定断开它的连接,但是成功登录后无法检索任何资源。

不过,我正在寻找的是我想更好地了解幕后情况。用户登录后,我会从rails端发送回X-CSRF-Token标头(form_authenticity_token),但据我了解,这仅是从iOS应用传递回服务器的必要操作,以便将操作写入服务器(POST,PUT,DELETE)。如果是这样,那么我如何向服务器标识自己以获取GET请求?

最佳答案

经过更多研究之后,这就是我总结自己所做的工作的方式。

  • 对于GET请求,请使用内置在iOS网络库中的cookie存储。默认情况下,该类在NSURLRequest(和可变变体)类中处于启用状态。这几乎是GET所需的全部。当然,您必须成功登录才能获取Cookie,并且登录需要POST。
  • 对于POST,PUT和DELETE,您必须在请求中提供X-CSRF-Token作为标头。但是,对于所有请求(登录请求除外)来说都是如此,登录请求将需要禁用X-CSRF-Token标头要求才能创建 session ,但在下文中有更多说明。

  • 首先,这是针对devise安装在iOS上登录的实现(更改了devise登录路由,即<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];
    }
    
  • 在铁轨方面,您将需要一种无需X-CSRF-Token即可创建 session 的方法,并且还需要在用户通过身份验证后将X-CSRF-Token传回,以便将来的写操作成功。

  • 我在 session 控制器中执行以下操作:
    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
    

    我的 session 控制器具有更多功能,但这显示了相关部分。成功执行创建操作的请求后,我发回X-CSRF-Token。但是,我跳过了对创建的真实性验证。这意味着尽管创建 session 本身不需要真实性 token ,但一旦操作完成,它将将一个 token 发送回请求者,以便请求者可以在以后的所有写操作中使用该 token 。

    如果我遗漏了一些东西或做错了什么,请让我知道,我将更新此答案。

    关于ios - Rails 4 iOS身份验证和授权,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23317127/

    10-12 07:34
    查看更多