Categories
Tags
Alamofire Android AppStoreConnect AWS Bun C++ cAdvisor CFW Cloudflare Cloudflare Access Cloudflare KV Cloudflare Tunnel Cloudflare Workers D1 Deno DevContainer Discord Docker ECR ECS Edizon Emulator EmuMMC Fastlane Firestore Frida Ghidra Git GitHub GitHub Actions GitLab GPG Grafana HACGUI Heroku Homebrew Hono IDA Pro iOS IPSwitch Jailbreak Javascript JSON JWT LanPlay Linode macOS Mirakurun MongoDB NestJS NextJS Nintendo Nintendo Switch NodeJS PHP PostgreSQL Prisma Programming Prometheus Python React Realm RealmSwift Ruby Salmon Run Salmonia3+ Shogi Sideload Snap Splatoon Splatoon2 Splatoon3 SSH Stable Diffusion Starlight Swift Swift Package SwiftUI Switch TensorRT Turf War Typescript TypeScript Ubuntu Ubuntu Server VNC VPN VSCode Vue WARP Wireguard XCode Xcode yarn zsh 家電 横歩取り
680 words
3 minutes
iOSで生体認証ロックを作ろう
iOS における生体認証
iOS では FaceID と TouchID の二つの生体認証がパスコード認証とは別に利用できる。
今回はその生体認証をアプリに組み込む方法について学ぶ。まず前提として、パスコードを含めた認証システムを使うにはimport LocalAuthentication
を読み込む必要がある。
認証のプロセス
- 生体認証が可能かどうかチェックする
- ここでパスコード認証を許可するかどうかを設定できる
- 可能であれば生体認証を行なう
- または生体認証をキャンセルしてパスコード認証を行なう
パスコード認証を許可するかどうかのフラグが何故あるかというと、iPhone5 以前のデバイスでは TouchID や FaceID が使用不可であり、そもそもそれ以降のデバイスでも生体認証を登録していないユーザがいるためである。
というわけで、全通りパターン分けをするとこのようになる。
func biometricsAuth() {
let context = LAContext()
let reason = "This app uses Touch ID / Face ID to secure your data."
var authError: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) {
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, error in
if success {
// 生体認証が成功した場合
} else {
// 生体認証が失敗した場合
}
}
} else {
// 生体認証ができない場合
}
}
指紋認証のためのボタンは SF symbols で定義されているtouchid
というやつが使える。
前回のコードとくっつける
パスコード入力画面に追加して動作チェックをしてみる。
import SwiftUI
import LocalAuthentication
struct PasscodeView: View {
typealias CompletionHandler = (Result<Bool, Error>) -> Void
let completionHandler: CompletionHandler
let passcode: Int
init(passcode: Int, completionHandler: @escaping CompletionHandler) {
self.completionHandler = completionHandler
self.passcode = passcode
}
var body: some View {
GeometryReader { geometry in
LazyVGrid(columns: Array(repeating: .init(.flexible(minimum: 60, maximum: 80), spacing: 0), count: 3), alignment: .center, spacing: 10, pinnedViews: []) {
ForEach(Range(1...9)) { number in
Button(action: { addSign(sender: number)}, label: { Text("\(number)").frame(width: 60, height: 60, alignment: .center) })
.overlay(Circle().stroke(Color.blue, lineWidth: 1))
}
.buttonStyle(CircleButtonStyle())
Button(action: { biometricsAuth() }, label: { Image(systemName: "touchid").resizable().frame(width: 40, height: 40, alignment: .center) })
Button(action: { addSign(sender: 0) }, label: { Text("0").frame(width: 60, height: 60, alignment: .center) })
.buttonStyle(CircleButtonStyle())
Button(action: {}, label: { Text("Delete").frame(width: 60, height: 60, alignment: .center) })
}
// 認証画面を真ん中に表示
.position(x: geometry.size.width / 2, y: geometry.size.height / 2)
}
.edgesIgnoringSafeArea(.all)
.background(Color.white)
}
func addSign(sender: Int) {
if sender == passcode {
completionHandler(.success(true))
} else {
completionHandler(.success(false))
}
}
func biometricsAuth() {
let context = LAContext()
let reason = "This app uses Touch ID / Face ID to secure your data."
var authError: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) {
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, error in
if success {
// 生体認証が成功した場合
print("SUCCESS")
} else {
// 生体認証が失敗した場合
print("FAILURE")
}
}
} else {
// 生体認証ができない場合
print("FAILURE")
}
}
}
struct CircleButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.foregroundColor(configuration.isPressed ? Color.white : Color.blue)
.overlay(Circle().stroke(Color.blue, lineWidth: 1))
.contentShape(Circle())
.background(Circle().foregroundColor(configuration.isPressed ? Color.blue : Color.clear))
}
}
iOSで生体認証ロックを作ろう
https://fuwari.vercel.app/posts/2021/04/biometrics/