很多時候啤贩,我們需要對訪問的URL進(jìn)行安全驗(yàn)證奴艾。我們通過這段向大家介紹如何通過Alamofire訪問需要HTTP簡單認(rèn)證的URL。
服務(wù)端的準(zhǔn)備
首先我們要在服務(wù)端添加一個需要安全驗(yàn)證的HTTP API辣恋,基于我們上一個的例子陈轿,打開routes.php贮配,添加下面的代碼:
Route::group(['middleware' => ['api']], function () {
Route::get('/alamofire', 'AlamofireController@index');
Route::post('/alamofire', [
'middleware' => 'auth.basic.once',
'uses' => 'AlamofireController@store']);
});
這里掘托,我們定義了一個auth.basic.once middleware茅诱,用于完成一個無狀態(tài)的HTTP簡單認(rèn)證金句。我們來實(shí)現(xiàn)它檩赢。
在Terminal里,進(jìn)入apidemo的項(xiàng)目目錄违寞,執(zhí)行下面的命令創(chuàng)建一個middleware:
php artisan make:middleware AuthenticateOnceWithBasicAuth
然后贞瞒,Laravel會在app/Http/Middleware目錄為我們創(chuàng)建一個AuthenticateOnceWithBasicAuth.php偶房,里面會包含一個同名的class。在它的Handle方法里军浆,我們添加下面的代碼:
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return Auth::onceBasic() ?: $next($request);
}
在這里Auth::onceBasic()為我們執(zhí)行一次無狀態(tài)的HTTP簡單認(rèn)證(它不會在session里寫上)棕洋,如果它沒有返回值,則代表認(rèn)證成功乒融,我們可以把請求轉(zhuǎn)發(fā)到后續(xù)的處理邏輯掰盘。否則,我們就返回Auth::onceBasic()提供的錯誤信息赞季。
完成之后愧捕,我們打開app/Http/Kernel.php,注冊我們之間添加的中間件:
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
// omit for simplicity
'auth.basic.once' => \App\Http\Middleware\AuthenticateOnceWithBasicAuth::class
];
這樣當(dāng)我們發(fā)起POST請求到/alamofire的時候申钩,服務(wù)器就會要求認(rèn)證晃财。為了測試,我們添加一個用戶帳號典蜕。
首先,在config/database.php里罗洗,我們把默認(rèn)的數(shù)據(jù)庫修改成sqlite(當(dāng)然愉舔,在.env里添加環(huán)境變量也可以):
'default' => env('DB_CONNECTION', 'sqlite'),
然后,在terminal里執(zhí)行:
php artisan migrate
這樣伙菜,Laravel就會在sqlite里創(chuàng)建users表轩缤,然后,執(zhí)行下面的命令:
php artisan tinker
這樣贩绕,我們就進(jìn)入了tinker的控制臺火的,在這里執(zhí)行下面的代碼:
App\User::create([
'email' => '11@boxue.io',
'password' => bcrypt('boxue'),
'name' => '11']);
這樣,我們就向數(shù)據(jù)庫中添加了一條User記錄淑倾。
最后,我們修改一下AlamofireController中處理POST /alamofire的代碼:
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
$data = $request->all();
return response()->json([
'status' => 'successful',
'data' => $data], 201);
}
接下來娇哆,我們使用POSTMAN驗(yàn)證一下湃累。
使用Postman
POSTMAN是一個Chrome app,可以很方便的幫我們測試各種HTTP API碍讨。我們可以在Chrome extension中找到它治力。它有兩個版本,一個是Chrome插件版勃黍,這個版本在Canary上有些問題宵统;還有一個是Chrome app,這里推薦大家使用app版覆获。
打開POSTMAN马澈,按照下圖中填寫我們的HTTP API信息:
當(dāng)我們選擇HTTP basic auth的時候瓢省,POSTMAN會自動為我們生成響應(yīng)HTTP header:
然后,我們隨便填寫一個POST BODY:
設(shè)置完成后箭券,點(diǎn)擊"Send"按鈕净捅,我們就可以看到返回的Status是201,內(nèi)容是我們返回的JSON辩块。
如果我們把密碼改成一個錯誤的值(例如下圖:)蛔六,然后重新發(fā)送請求,就可以看到服務(wù)器返回的401 - invalid credentials錯誤了废亭。
在服務(wù)端搞定認(rèn)證之后国章,接下來,我們來看如何用Alamofire替代POSTMAN發(fā)送請求豆村。
使用Alamofire完成請求
在搞定了前面的各種配置和代碼之后液兽,用Alamofire發(fā)送請求倒是顯得格外簡單。我們有兩種不同的方法可以通過Alamofire訪問需要HTTP簡單認(rèn)證的API掌动。
調(diào)用authenticate方法
這是最簡單的方法四啰,Alamofire有一個authenticate方法,我們直接拿來用就可以了:
回到Xcode粗恢,在ViewDidLoad方法里柑晒,添加下面的代碼:
let user = "11@boxue.io"
let pw = "boxue"
Alamofire.request(.POST, "https://apidemo.boxue.io/alamofire")
.authenticate(user: user, password: pw)
.responseJSON(completionHandler: { response in
debugPrint(response)
})
按Command + R,就可以在控制臺眷射,看到了對應(yīng)的結(jié)果了:
除了給authenticate傳遞用戶名和密碼外匙赞,我們還可以傳給它傳遞一個NSURLCredential對象:
let user = "11@boxue.io"
let pw = "boxue"
let credential = NSURLCredential(user: user,
password: pw,
persistence: .ForSession)
Alamofire.request(.POST, "https://apidemo.boxue.io/alamofire")
.authenticate(usingCredential: credential)
.responseJSON(completionHandler: { response in
debugPrint(response)
})
按Command + R,重新編譯執(zhí)行妖碉,我們就可以在控制臺里看到涌庭,結(jié)果是一樣的。
自行構(gòu)造HTTP header
除了使用authenticate方法之外欧宜,我們也可以手工構(gòu)造一個和POSTMAN一樣的HTTP header坐榆,用于HTTP basic authentication:
let credentialData =
"\(user):\(pw)".dataUsingEncoding(NSUTF8StringEncoding)!
let base64Credentials =
credentialData.base64EncodedStringWithOptions([])
let headers = ["Authorization": "Basic \(base64Credentials)"]
然后,我們把這個header添加到POST請求就可以了:
Alamofire.request(.POST,
"https://apidemo.boxue.io/alamofire",
headers: headers)
.responseJSON(completionHandler: { response in
debugPrint(response)
})
按Command + R冗茸,重新編譯執(zhí)行猛拴,我們就可以在控制臺里看到,結(jié)果是一樣的蚀狰。