2010-04-18 3 views
25

iPhone 응용 프로그램에서 응용 프로그램이 다시 시작될 때 동일한 서버 측 세션을 다시 사용할 수 있어야합니다. 서버의 세션은 각 요청에 대해 전송되는 쿠키로 식별됩니다. 앱을 다시 시작하면 쿠키가 사라지고 더 이상 동일한 세션을 사용할 수 없습니다.iPhone : 응용 프로그램 재시작시 NSHTTPCookie가 저장되지 않습니다.

NSHTTPCookieStorage을 사용하여 서버에서 가져온 쿠키를 조회했을 때 주목할 점은 [cookie isSessionOnly]YES입니다. 이것이 내 앱 재시작시 쿠키가 저장되지 않는 이유입니다. 내 쿠키를 세션으로 만 사용하려면 어떻게해야합니까? 어떤 HTTP 헤더를 서버에서 보내야합니까?

답변

41

속성 사전을 저장 한 다음 다시 연결하기 전에 새 쿠키로 복원하여 쿠키를 저장할 수 있습니다.

저장 :

NSArray* allCookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:URL]]; 
for (NSHTTPCookie *cookie in allCookies) { 
    if ([cookie.name isEqualToString:MY_COOKIE]) { 
     NSMutableDictionary* cookieDictionary = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey:PREF_KEY]]; 
     [cookieDictionary setValue:cookie.properties forKey:URL]; 
     [[NSUserDefaults standardUserDefaults] setObject:cookieDictionary forKey:PREF_KEY]; 
    } 
} 

로드 : 나는 TomIrving의 대답 @ upvoted하고 많은 사용자가 매우 중요 코멘트를 볼 수 없기 때문에 여기 정교화하고

NSDictionary* cookieDictionary = [[NSUserDefaults standardUserDefaults] dictionaryForKey:PREF_KEY]; 
NSDictionary* cookieProperties = [cookieDictionary valueForKey:URL]; 
if (cookieProperties != nil) { 
    NSHTTPCookie* cookie = [NSHTTPCookie cookieWithProperties:cookieProperties]; 
    NSArray* cookieArray = [NSArray arrayWithObject:cookie]; 
    [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookieArray forURL:[NSURL URLWithString:URL] mainDocumentURL:nil]; 
} 
+1

nsuserdefaults를 동기화해야합니까? – ninjaneer

+1

바로 저장해야하는 경우 동기화가 필요합니다. 그렇지 않으면 그들은 나중에 어떤 중간 시대에 구원받을 것입니다. 다음은 doc 페이지입니다. http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html#//apple_ref/occ/instm/NSUserDefaults/synchronize –

2

저는 쿠키가 세션 전용인지 여부를 결정하는 것은 서버에 달려 있다고 생각합니다. 귀하는 그것에 대해 아무 것도 할 수 없습니다.

+0

아니요, 실제로 세션 쿠키를 버리는 클라이언트 (iPhone 앱)입니다. 세션이 여전히 서버에 있습니다. –

+3

맞습니다.하지만 서버는 쿠키가 세션 전용이라는 것을 iPhone 앱에 알립니다. –

+1

예, HTTP를 통한 것입니다. 그래서 정확한 헤더를 서버에서 보내어 아이폰 앱에 쿠키를 오래 보관할 수 있다고 말하고 싶습니다. –

18

는 그는 말한다 :

"만료일을 설정해야합니다. 그렇지 않으면 쿠키는 세션으로 만 간주됩니다."

기본적으로 쿠키의 만료일이 남아 있지 않으면 앱을 닫을 때 쿠키가 삭제됩니다.

서버를 제어 할 수 있고 나중에 "만료"헤더를 설정하도록 요청할 수있는 경우 NSUserDefaults에서 또는 그 이상으로 쿠키를 저장하고 복원 할 필요가 없습니다. 당신은 서버를 제어 할 수 없거나 서버의 행동, 당신이 할 수있는 '트릭'그것은 내에서 expiresDate을 변경하여 응용 프로그램을 무시하지 않으려면 :

  • 당신이 [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]에서 수정할 쿠키를 가져옵니다
  • NSMutableDictionary에 속성을 복사하고 "Expires" 값을 미래의 날짜로 변경합니다.
  • 사용하여 새로운 NSMutableDictionary에서 새 쿠키를 만듭니다 [NSHTTPCookie.cookieWithProperties:]
  • 를 저장 앱을 다시 열 때

[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie newCookie], 당신은 쿠키가 삭제되지 않았 음을 알 수 있습니다 사용하여 새로 만든 쿠키를.

+2

서버 측 보안 접근법에서 이것은 허용 된 대답이어야합니다. – MandisaW

1

스위프트 방법

스토어 :

static func storeCookies() { 
    let cookiesStorage = NSHTTPCookieStorage.sharedHTTPCookieStorage() 
    let userDefaults = NSUserDefaults.standardUserDefaults() 

    let serverBaseUrl = "http://yourserverurl.com" 
    var cookieDict = [String : AnyObject]() 

    for cookie in cookiesStorage.cookiesForURL(NSURL(string: serverBaseUrl)!)! { 
     cookieDict[cookie.name] = cookie.properties 
    } 

    userDefaults.setObject(cookieDict, forKey: cookiesKey) 
} 

복원 :

static func restoreCookies() { 
    let cookiesStorage = NSHTTPCookieStorage.sharedHTTPCookieStorage() 
    let userDefaults = NSUserDefaults.standardUserDefaults() 

    if let cookieDictionary = userDefaults.dictionaryForKey(cookiesKey) { 

     for (cookieName, cookieProperties) in cookieDictionary { 
      if let cookie = NSHTTPCookie(properties: cookieProperties as! [String : AnyObject]) { 
       cookiesStorage.setCookie(cookie) 
      } 
     } 
    } 
} 
4

는 세션 전용 쿠키가 자연 만료됩니다. 키 체인을 원할 경우 수동으로 키 체인에 저장할 수 있습니다.나는 UserDefaults에 저장하거나 보관하는 것이 키 체인보다 사용자의 암호처럼 쿠키가 더 안전하기 때문에 선호합니다.

불행히도 세션 전용 쿠키를 저장하는 것은별로 도움이되지 않습니다. 아래의 코드는 쿠키를 저장하는 방법을 보여 주지만 서버를 제어 할 수있는 경우를 제외하고 서버가 쿠키를 허용하지 않습니다.

스위프트 2.2

// Saving into Keychain 
if let cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies { 
    let cookiesData: NSData = NSKeyedArchiver.archivedDataWithRootObject(cookies) 
    let userAccount = "some unique string to identify the item in Keychain, in my case I use username" 
    let domain = "some other string you can use in combination with userAccount to identify the item"   
    let keychainQuery: [NSString: NSObject] = [ 
         kSecClass: kSecClassGenericPassword, 
         kSecAttrAccount: userAccount + "cookies", 
         kSecAttrService: domain, 
         kSecValueData: cookiesData] 
    SecItemDelete(keychainQuery as CFDictionaryRef) //Trying to delete the item from Keychaing just in case it already exists there 
    let status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil) 
    if (status == errSecSuccess) { 
     print("Cookies succesfully saved into Keychain") 
    } 
} 

// Getting from Keychain 
let userAccount = "some unique string to identify the item in Keychain, in my case I use username" 
let domain = "some other string you can use in combination with userAccount to identify the item" 
let keychainQueryForCookies: [NSString: NSObject] = [ 
          kSecClass: kSecClassGenericPassword, 
          kSecAttrService: domain, // we use JIRA URL as service string for Keychain 
          kSecAttrAccount: userAccount + "cookies", 
          kSecReturnData: kCFBooleanTrue, 
          kSecMatchLimit: kSecMatchLimitOne] 
var rawResultForCookies: AnyObject? 
let status: OSStatus = SecItemCopyMatching(keychainQueryForCookies, &rawResultForCookies) 
if (status == errSecSuccess) { 
    let retrievedData = rawResultForCookies as? NSData 
    if let unwrappedData = retrievedData { 
     if let cookies = NSKeyedUnarchiver.unarchiveObjectWithData(unwrappedData) as? [NSHTTPCookie] { 
      for aCookie in cookies { 
       NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookie(aCookie) 
      } 
     } 
    } 
} 
0

SWIFT 3

SAVE :

if let httpResponse = response as? HTTPURLResponse, let fields = httpResponse.allHeaderFields as? [String : String] { 
      let cookies = HTTPCookie.cookies(withResponseHeaderFields: fields, for: response.url!) 
      HTTPCookieStorage.shared.setCookies(cookies, for: response.url!, mainDocumentURL: nil) 
      for cookie in cookies { 
       if cookie.name == cookieName{ 
        if cookieName == Constants.WS.COOKIES.COOKIE_SMS { 
         UserDefaults.standard.set(NSKeyedArchiver.archivedData(withRootObject: cookie), forKey: Constants.SHARED_DEFAULT.COOKIE_SMS) 
         UserDefaults.standard.synchronize() 
        } 

        return cookie.value 
       } 
      } 
     } 

GET :

let cookie: HTTPCookie = NSKeyedUnarchiver.unarchiveObject(with: UserDefaults.standard.object(forKey: Constants.SHARED_DEFAULT.COOKIE_SMS) as! Data) as! HTTPCookie 
     HTTPCookieStorage.shared.setCookie(cookie) 
관련 문제