Skip to content

Commit

Permalink
#11 KeyChain 적용
Browse files Browse the repository at this point in the history
  • Loading branch information
heejinnn committed Oct 28, 2023
1 parent eacb224 commit 692c2a7
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 52 deletions.
4 changes: 4 additions & 0 deletions fit-a-pet-client/fit-a-pet-client.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
4A00A90C2AC66BDC007AEC8A /* UserModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A00A90B2AC66BDC007AEC8A /* UserModel.swift */; };
4A037FF22AED62E30073BB56 /* KeyChainHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A037FF12AED62E30073BB56 /* KeyChainHelper.swift */; };
4A15F2072AA641910098F2F7 /* CustomNextBtn.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A15F2062AA641910098F2F7 /* CustomNextBtn.swift */; };
4A15F2092AA790D60098F2F7 /* CustomProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A15F2082AA790D60098F2F7 /* CustomProgressBar.swift */; };
4A15F20B2AA799C50098F2F7 /* ConstomLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A15F20A2AA799C50098F2F7 /* ConstomLabel.swift */; };
Expand Down Expand Up @@ -49,6 +50,7 @@
/* Begin PBXFileReference section */
1BE018CCB6881B4EFC5C6D84 /* Pods-fit-a-pet-client.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fit-a-pet-client.release.xcconfig"; path = "Target Support Files/Pods-fit-a-pet-client/Pods-fit-a-pet-client.release.xcconfig"; sourceTree = "<group>"; };
4A00A90B2AC66BDC007AEC8A /* UserModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserModel.swift; sourceTree = "<group>"; };
4A037FF12AED62E30073BB56 /* KeyChainHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyChainHelper.swift; sourceTree = "<group>"; };
4A15F2062AA641910098F2F7 /* CustomNextBtn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomNextBtn.swift; sourceTree = "<group>"; };
4A15F2082AA790D60098F2F7 /* CustomProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomProgressBar.swift; sourceTree = "<group>"; };
4A15F20A2AA799C50098F2F7 /* ConstomLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstomLabel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -200,6 +202,7 @@
children = (
4A4BFDC92AD26B0F0062BDB8 /* RegistrationManager.swift */,
4A8B9B4F2AD444D0009236EC /* Constants.swift */,
4A037FF12AED62E30073BB56 /* KeyChainHelper.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -397,6 +400,7 @@
4ACDD4A32AD9B3A500CD8F1A /* InputPetNameVC.swift in Sources */,
4AD3542D2AAF7F83004A47B3 /* SettingVC.swift in Sources */,
4A15F2122AA8B4880098F2F7 /* InputIdVC.swift in Sources */,
4A037FF22AED62E30073BB56 /* KeyChainHelper.swift in Sources */,
4AD354292AAF7F55004A47B3 /* RecordVC.swift in Sources */,
4A15F2092AA790D60098F2F7 /* CustomProgressBar.swift in Sources */,
4A9088772AC1681B000C7878 /* PetCollectViewCell.swift in Sources */,
Expand Down
Binary file not shown.
64 changes: 29 additions & 35 deletions fit-a-pet-client/fit-a-pet-client/API/AlamofireManager.swift
Original file line number Diff line number Diff line change
@@ -1,95 +1,89 @@


import Foundation
import Alamofire
import os.log

class AlamofireManager{
class AlamofireManager {

//싱글턴 적용
static let shared = AlamofireManager()//자기 자신의 인스턴스를 가져옴
// 싱글턴 적용
static let shared = AlamofireManager() // 자기 자신의 인스턴스를 가져옴

//로거 설정
//자료형이 EventMonitor
let monitors = [MyLogger(), ApiStatusLogger()] as [EventMonitor]//여러개 추가 가능
// 로거 설정
// 자료형이 EventMonitor
let monitors = [MyLogger(), ApiStatusLogger()] as [EventMonitor] // 여러 개 추가 가능

let session = Session.default

//MARK: - Alamofire methods
func sendSms(_ phone: Int, completion: @escaping(Result<Data?, Error>) -> Void) {
// MARK: - Alamofire methods
func sendSms(_ phone: String, completion: @escaping(Result<Data?, Error>) -> Void) {

print("MyAlamofireManager - sendSms() called userInput : \(phone) ")
os_log("MyAlamofireManager - sendSms() called userInput : %@", log: .default, type: .info, phone)

self
.session //세션 설정
.session // 세션 설정
.request(MySearchRouter.sendSms(to: phone))
// .validate(statusCode: 200..<401)//200에서 401이전까지만
.response { response in
switch response.result {
case .success(let data):
completion(.success(data))
case .failure(let error):
completion(.failure(error))
}
}

}
}

func checkSms(_ phone: Int, _ code: Int, completion: @escaping(Result<Data?, Error>) -> Void) {

print("MyAlamofireManager - checkSms() called userInput : \(phone) ,, \(code) ")
func checkSms(_ phone: String, _ code: Int, completion: @escaping(Result<Data?, Error>) -> Void) {
os_log("MyAlamofireManager - checkSms() called userInput : %@ ,, %d", log: .default, type: .info, phone, code)

self
.session
.request(MySearchRouter.checkSms(to: phone, code: code))
self.session.request(MySearchRouter.checkSms(to: phone, code: code))
.response { response in
switch response.result {
case .success(let data):
//액세스 토큰 저장
if let responseHeaders = response.response?.allHeaderFields as? [String: String],
let accessToken = responseHeaders["accessToken"] {
UserDefaults.standard.set(accessToken, forKey: "accessToken")
print("AccessToken: \(accessToken)")
KeychainHelper.saveAccessToken(accessToken: accessToken)
}

completion(.success(data))
case .failure(let error):
completion(.failure(error))
}
}
}
}

func login(_ uid: String, _ password: String, completion: @escaping(Result<Data?, Error>) -> Void){
print("MyAlamofireManager - login() called userInput : \(uid) ,, \(password) ")

os_log("MyAlamofireManager - login() called userInput : %@ ,, %@", log: .default, type: .info, uid, password)

self
.session
.request(MySearchRouter.login(uid: uid, password: password))
.response{ response in
.response { response in
switch response.result{
case .success(let data):
if let responseHeaders = response.response?.allHeaderFields as? [String: String],
let accessToken = responseHeaders["accessToken"] {
KeychainHelper.saveAccessToken(accessToken: accessToken)
os_log("login token: %@", log: .default, type: .info, accessToken)
}
completion(.success(data))
case .failure(let error):
completion(.failure(error))
}

}
}
}

func regist(_ uid: String, _ name: String, _ password: String, _ email: String, _ profileImg: String, completion: @escaping(Result<Data?, Error>) -> Void){
print("MyAlamofireManager - regist() called userInput : \(uid) ,, \(password) ,, \(name) ,, \(email) ,, \(profileImg) ")
os_log("MyAlamofireManager - regist() called userInput : %@ ,, %@ ,, %@ ,, %@ ,, %@", log: .default, type: .info, uid, password, name, email, profileImg)

self
.session
.request(MySearchRouter.regist(uid: uid, name: name, password: password, email: email, profileImg: profileImg))
.response{ response in
.response { response in
switch response.result{
case .success(let data):
completion(.success(data))
case .failure(let error):
completion(.failure(error))
}

}
}
}
}

25 changes: 15 additions & 10 deletions fit-a-pet-client/fit-a-pet-client/API/MySearchRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import os.log

enum MySearchRouter: URLRequestConvertible {

case sendSms(to: Int)
case checkSms(to: Int, code: Int)
case sendSms(to: String)
case checkSms(to: String, code: Int)
case login(uid: String, password: String)
case regist(uid: String, name: String, password: String, email: String, profileImg: String)

Expand Down Expand Up @@ -53,30 +53,35 @@ enum MySearchRouter: URLRequestConvertible {
return ["uid": uid, "name": name, "password": password, "email": email, "profileImg": profileImg]
}
}

func asURLRequest() throws -> URLRequest {
let url = baseURL.appendingPathComponent(path)
var request: URLRequest

if case .checkSms(let to, let code) = self {
switch self {
case .checkSms(let to, let code):
// checkSms 케이스에서 "to"는 바디로, "code"는 쿼리로 처리
request = createURLRequestForBodyAndQuery(url: url, to: to, code: code)
} else if case .regist = self {
if let accessToken = UserDefaults.standard.string(forKey: "accessToken") {
// accesstoken 헤더로 보내기

case .regist:
// regist 케이스에만 Keychain 사용
if let accessToken = KeychainHelper.loadAccessToken() {
// accessToken을 Keychain에서 불러와서 헤더로 보내기
request = createURLRequestForBody(url: url)
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
} else {
request = createURLRequestForBody(url: url)
}
} else {
// sendSms 및 login 케이스에서 body로 처리

default:
// sendSms 케이스에서 body로 처리
request = createURLRequestForBody(url: url)
}

return request
}


private func createURLRequestForQuery(url: URL) -> URLRequest {
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
components?.queryItems = parameters.map { key, value in
Expand Down Expand Up @@ -105,7 +110,7 @@ enum MySearchRouter: URLRequestConvertible {
return request
}

private func createURLRequestForBodyAndQuery(url: URL, to: Int, code: Int) -> URLRequest {
private func createURLRequestForBodyAndQuery(url: URL, to: String, code: Int) -> URLRequest {
var request = URLRequest(url: url)
request.httpMethod = method.rawValue

Expand Down
37 changes: 37 additions & 0 deletions fit-a-pet-client/fit-a-pet-client/Utils/KeyChainHelper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Foundation
import Security

class KeychainHelper {
static func saveAccessToken(accessToken: String) {
let keychainQuery: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccount: "accessToken",
kSecValueData: accessToken.data(using: .utf8)!,
]

let status = SecItemAdd(keychainQuery as CFDictionary, nil)
if status == errSecDuplicateItem {
SecItemUpdate(keychainQuery as CFDictionary, [kSecValueData: accessToken.data(using: .utf8)!] as CFDictionary)
} else if status != noErr {
print("Failed to save AccessToken to Keychain")
}
}

static func loadAccessToken() -> String? {
let query: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccount: "accessToken",
kSecReturnData: kCFBooleanTrue,
]

var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)

if status == noErr, let data = item as? Data, let token = String(data: data, encoding: .utf8) {
return token
} else {
return nil
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ struct RegistrationManager {
var id: String?
var pw: String?
var nickname: String?
var phone: Int?
var phone: String?

// Singleton 패턴을 위한 private 생성자
private init() {}

// 입력 값을 저장하는 메서드
mutating func addInput(id: String? = nil, pw: String? = nil, nickname: String? = nil, phone: Int? = nil) {
mutating func addInput(id: String? = nil, pw: String? = nil, nickname: String? = nil, phone: String? = nil) {
if let id = id {
self.id = id
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class InputAuthNumVC : UIViewController{
let progressBar = CustomProgressBar.shared
let customLabel = ConstomLabel()

var phone: Int = 0
var phone: String = ""
var code: Int = 0

override func viewDidLoad() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class InputNickVC : UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)

RegistrationManager.shared.addInput(nickname: "최희진")
RegistrationManager.shared.addInput(nickname: "최희진2")
RegistrationManager.shared.performRegistration()

self.navigationController?.navigationBar.tintColor = .black
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class InputPhoneNumVC : UIViewController {
let progressBar = CustomProgressBar.shared
let customLabel = ConstomLabel()

var phone: Int = 0
var phone: String = ""

override func viewDidLoad() {
super.viewDidLoad()
Expand Down Expand Up @@ -110,7 +110,6 @@ class InputPhoneNumVC : UIViewController {
let object = try?JSONSerialization.jsonObject(with: responseData, options: []) as? NSDictionary
guard let jsonObject = object else {return}
print("respose jsonData: \(jsonObject)")
// print("Received data: \(responseData)")
}
case .failure(let error):
// Handle failure
Expand Down Expand Up @@ -149,7 +148,7 @@ extension InputPhoneNumVC: UITextFieldDelegate{

if strippedPhoneNumber.count == 11 {
formattedText = String(strippedPhoneNumber.prefix(10))
phone = Int(strippedPhoneNumber) ?? 0
phone = strippedPhoneNumber
print("phone: \(phone)")
return false
} else {
Expand Down

0 comments on commit 692c2a7

Please sign in to comment.