<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 服務 —— 用戶認證 ## 1、簡介 Laravel中實現用戶非常簡單。實際上,幾乎所有東西都已經為你配置好了。配置文件位于`config/auth.php`,其中包含了用于調整認證服務行為的、文檔友好的選項配置。 ### 1.1 數據庫考量 默認情況下,Laravel在`app`目錄下包含了一個[Eloquent](http://laravelacademy.org/post/138.html)模型`App\User`,這個模型可以和默認的Eloquent認證驅動一起使用。如果你的應用不使用Eloquent,你可以使用`database`認證驅動,該驅動使用了Laravel查詢構建器。 為`App\User`模型構建數據庫表結構的時候,確保`password`字段長度至少有60位。 還有,你應該驗證`users`表包含了可以為空的、字符串類型的`remember_token`字段長度為100,該字段用于存儲被應用維護的”記住我(remember me)“的session令牌,這可以通過在遷移中使用`$table->rememberToken();`來實現。 ## 2、用戶認證快速入門 Laravel處理兩個認證控制器,位于`App\Http\Controllers\Auth和認證,`PasswordController`包含幫助用戶找回密碼的邏輯。每個控制器都使用trait來引入它們需要的方法。對很多應用而言,你根本不需要修改這兩個控制器。 ### 2.1?路由 默認情況下,沒有路由將請求指向用戶認證控制器,你要手動在`app/Http/routes.php`文件中添加它們: ~~~ // 認證路由... Route::get('auth/login', 'Auth\AuthController@getLogin'); Route::post('auth/login', 'Auth\AuthController@postLogin'); Route::get('auth/logout', 'Auth\AuthController@getLogout'); // 注冊路由... Route::get('auth/register', 'Auth\AuthController@getRegister'); Route::post('auth/register', 'Auth\AuthController@postRegister'); ~~~ ### 2.2 視圖 盡管框架包含了用戶認證控制器,你還是需要提供這些控制器可以渲染的[視圖](http://laravelacademy.org/post/76.html)。這些視圖位于`resources/views/auth`目錄,你可以按需自定義視圖是`resources/views/auth/login.blade.php`,注冊視圖是`resources/views/auth/register.blade.php`。 ### 2.2.1 登錄表單示例 ~~~ <!-- resources/views/auth/login.blade.php --> <form method="POST" action="/auth/login"> {!! csrf_field() !!} <div> Email <input type="email" name="email" value="{{ old('email') }}"> </div> <div> Password <input type="password" name="password" id="password"> </div> <div> <input type="checkbox" name="remember"> Remember Me </div> <div> <button type="submit">Login</button> </div> </form> ~~~ ### 2.2.2 注冊表單示例 ~~~ <!-- resources/views/auth/register.blade.php --> <form method="POST" action="/auth/register"> {!! csrf_field() !!} <div> Name <input type="text" name="name" value="{{ old('name') }}"> </div> <div> Email <input type="email" name="email" value="{{ old('email') }}"> </div> <div> Password <input type="password" name="password"> </div> <div> Confirm Password <input type="password" name="password_confirmation"> </div> <div> <button type="submit">Register</button> </div> </form> ~~~ ### 2.3 認證 既然你已經為自帶的認證控制器設置好了路由和視圖,接下來就準備為應用注冊新用戶并進行登錄認證。你可以在瀏覽器中訪問定義好的路由,認證控制器已經實現了認證已存在用戶以及存儲新用戶到數據庫中的業務邏輯(通過trait)。 當一個用戶成功進行登錄認證后,將會跳轉到/home鏈接,你需要事先注冊一個路由來處理該跳轉。你可以通過在`AuthController`中設置`redirectPath`屬性來自定義post認證之后的跳轉路徑: ~~~ protected $redirectPath = '/dashboard'; ~~~ 當一個用戶登錄認證失敗后,將會跳轉到`/auth/login`鏈接。你可以通過定義`AuthController`的`loginPath`屬性來自定義post認證失敗后的跳轉路徑: ~~~ protected $loginPath = '/login'; ~~~ ### 2.3.1 自定義 要修改新用戶注冊所必需的表單字段,或者自定義新用戶字段如何存儲到數據庫,你可以修改`AuthController`類。該類負責為應用驗證和創建新用戶。 `AuthController`的`validator`方法包含了新用戶的驗證規則,你可以隨意按需要自定義該方法。 `AuthController`的`create`方法負責使用[Eloquent ORM](http://laravelacademy.org/post/138.html)在數據庫中創建新的`App\User`記錄。你可以基于自己的需要隨意自定義該方法。 ### 2.4 獲取認證用戶 你可以通過`Auth`門面訪問認證用戶: ~~~ $user = Auth::user(); ~~~ 一旦用戶通過認證后,你還可以通過`Illuminate\Http\Request`實例訪問認證用戶: ~~~ <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Routing\Controller; class ProfileController extends Controller{ /** * 更新用戶屬性. * * @param Request $request * @return Response */ public function updateProfile(Request $request) { if ($request->user()) { // $request->user() 返回認證用戶實例... } } } ~~~ ### 2.4.1 判斷當前用戶是否通過認證 要判斷某個用戶是否登錄到應用,可以使用`Auth`[門面](http://laravelacademy.org/post/97.html)的`check`方法,如果用戶通過認證則返回`true`: ~~~ if (Auth::check()) { // The user is logged in... } ~~~ 此外,你還可以在用戶訪問特定路由/控制器之前使用中間件來驗證用戶是否通過認證,想要了解更多,可以查看[路由保護文檔](http://laravelacademy.org/post/163.html#route-protect)。 ### 2.5 路由保護 [路由中間件](http://laravelacademy.org/post/57.html)可用于只允許通過認證的用戶訪問給定路由。Laravel通過定義在`app\Http\Middleware\Authenticate.php`的`auth`中間件來處理這一操作。你所要做的僅僅是將該中間件加到相應的路由定義中: ~~~ // 使用路由閉包... Route::get('profile', ['middleware' => 'auth', function() { // 只有認證用戶可以進入... }]); // 使用控制器... Route::get('profile', [ 'middleware' => 'auth', 'uses' => 'ProfileController@show' ]); ~~~ 當然,如果你正在使用[控制器類](http://laravelacademy.org/post/60.html),也可以在控制器的構造方法中調用`middleware`方法而不是在路由器中直接定義: ~~~ public function __construct(){ $this->middleware('auth'); } ~~~ ### 2.6 登錄失敗次數限制 如果你正在使用Laravel內置的`AuthController`類,`Illuminate\Foundation\Auth\ThrottlesLogins`?trait 可以用于限制用戶登錄失敗次數。默認情況下,用戶在幾次登錄失敗后將在一分鐘內不能登錄,這種限制基于用戶的用戶名/郵箱地址+IP地址: ~~~ <?php namespace App\Http\Controllers\Auth; use App\User;use Validator; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\ThrottlesLogins; use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers; class AuthController extends Controller{ use AuthenticatesAndRegistersUsers, ThrottlesLogins; // AuthController類的其它部分... } ~~~ ## 3、手動認證用戶 當然,你也可以不使用Laravel自帶的認證控制器。如果你選擇移除這些控制器,你需要直接使用Laravel認證類來管理用戶認證。別擔心,這很簡單! 我們將會通過`Auth`門面來訪問認證服務,因此我們需要確保在類的頂部導入了`Auth`[門面](http://laravelacademy.org/post/97.html),讓我們看看`attempt`方法: ~~~ <?php namespace App\Http\Controllers; use Auth; use Illuminate\Routing\Controller; class AuthController extends Controller{ /** * 處理登錄認證 * * @return Response */ public function authenticate() { if (Auth::attempt(['email' => $email, 'password' => $password])) { // 認證通過... return redirect()->intended('dashboard'); } } } ~~~ `attempt`方法接收鍵值數組對作為第一個參數,數組中的值被用于從數據表中查找用戶,因此,在上面的例子中,用戶將會通過`email`的值獲取,如果用戶被找到,經哈希運算后存儲在數據中的密碼將會和傳遞過來的經哈希運算處理的密碼值進行比較。如果兩個經哈希運算的密碼相匹配那么一個認證session將會為這個用戶開啟。 如果認證成功的話`attempt`方法將會返回`true`。否則,返回`false`。 重定向器上的`intended`方法將會將用戶重定向到登錄之前用戶想要訪問的URL,在目標URL無效的情況下備用URI將會傳遞給該方法。 如果你想的話,除了用戶郵件和密碼之外還可以在認證查詢時添加額外的條件,例如,我們可以驗證被標記為有效的用戶: ~~~ if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) { // The user is active, not suspended, and exists. } ~~~ 要退出應用,可以使用`Auth`門面的`logout`方法,這將會清除用戶session中的認證信息: ~~~ Auth::logout(); ~~~ > 注意:在這些例子中,`email`并不是必須選項,在這里只不過是作為一個例子。你可以在自己的數據庫使用任何其他與“用戶名”相對應的字段。 ### 3.1 記住用戶 如果你想要在應用中提供“記住我”的功能,可以傳遞一個布爾值作為第二個參數到`attempt`方法,這樣用戶登錄認證狀態就會一直保持直到他們手動退出。當然,你的`users`表必須包含`remember_token`字段,該字段用于存儲“記住我”令牌。 ~~~ if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) { // The user is being remembered... } ~~~ 如果你要“記住”用戶,可以使用`viaRemember`方法來判斷用戶是否使用“記住我”cookie進行認證: ~~~ if (Auth::viaRemember()) { // } ~~~ ### 3.2 其它認證方法 ### 3.2.1 認證用戶實例 如果你需要將一個已存在的用戶實例登錄到應用中,可以調用用戶實例上的`login`方法,給定實例必須是`Illuminate\Contracts\Auth\Authenticatable`[契約](http://laravelacademy.org/post/95.html)的實現,當然,Laravel自帶的`App\User`模型已經實現了該接口: ~~~ Auth::login($user); ~~~ ### 3.2.2 通過ID認證用戶 要通過用戶ID登錄到應用,可以使用`loginUsingId`方法,該方法接收你想要認證用戶的主鍵作為參數: ~~~ Auth::loginUsingId(1); ~~~ ### 3.2.3 一次性認證用戶 你可以使用`once`方法只在單個請求中將用戶登錄到應用,而不存儲任何session和cookie,這在構建無狀態的API時很有用。`once`方法和`attempt`方法用法差不多: ~~~ if (Auth::once($credentials)) { // } ~~~ ## 4、基于HTTP的基本認證 [HTTP基本認證](http://en.wikipedia.org/wiki/Basic_access_authentication)能夠幫助用戶快速實現登錄認證而不用設置專門的登錄頁面,首先要在路由中加上`auth.basic`[中間件](http://laravelacademy.org/post/57.html)。該中間件是Laravel自帶的,所以不需要自己定義: ~~~ Route::get('profile', ['middleware' => 'auth.basic', function() { // 只有認證用戶可以進入... }]); ~~~ 中間件加到路由中后,當在瀏覽器中訪問該路由時,會自動提示需要認證信息,默認情況下,`auth.basic`中間件使用用戶記錄上的`email`字段作為“用戶名”。 **FastCGI上注意點** 如果你使用PHP FastCGI,HTTP基本認證將不能正常工作,需要在`.htaccess`文件加入如下內容: ~~~ RewriteCond %{HTTP:Authorization} ^(.+)$ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] ~~~ ### 4.1 無狀態的HTTP基本認證 使用HTTP基本認證也不需要在session中設置用戶標識cookie,這在API認證中非常有用。要實現這個,需要定義一個調用`onceBasic`方法的中間件。如果該方法沒有返回任何響應,那么請求會繼續走下去: ~~~ <?php namespace Illuminate\Auth\Middleware; use Auth; use Closure; class AuthenticateOnceWithBasicAuth{ /** * 處理輸入請求. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { return Auth::onceBasic() ?: $next($request); } } ~~~ 接下來,注冊路由中間件并將其添加到路由中: ~~~ Route::get('api/user', ['middleware' => 'auth.basic.once', function() { // 只有認證用戶可以進入... }]); ~~~ ## 5、重置密碼 ### 5.1?數據庫考量 大多數web應用提供了用戶重置密碼的功能,Laravel提供了便利方法用于發送密碼提示及執行密碼重置而不需要你在每個應用中重新實現。 開始之前,先驗證`App\User`模型實現了`Illuminate\Contracts\Auth\CanResetPassword`契約。當然,Laravel自帶的`App\User`模型已經實現了該接口,并使用`Illuminate\Auth\Passwords\CanResetPassword`?trait來包含實現該接口需要的方法。 ### 5.1.1 生成重置令牌表遷移 接下來,用來存儲密碼重置令牌的表必須被創建,Laravel已經自帶了這張表的遷移,就存放在`database/migrations`目錄。所有,你所要做的僅僅是運行遷移: ~~~ php artisan migrate ~~~ ### 5.2 路由 Laravel自帶了`Auth\PasswordController`,其中包含重置用戶必須的邏輯。然而,你需要定義一個路由將請求轉發到該控制器: ~~~ // 密碼重置鏈接請求路由... Route::get('password/email', 'Auth\PasswordController@getEmail'); Route::post('password/email', 'Auth\PasswordController@postEmail'); // 密碼重置路由... Route::get('password/reset/{token}', 'Auth\PasswordController@getReset'); Route::post('password/reset', 'Auth\PasswordController@postReset'); ~~~ ### 5.3 視圖 除了為`Auth\PasswordController`定義路由之外,還需要提供相應視圖,別擔心,我們將會提供示例視圖來幫助你開始,當然,你也可以自定義表單樣式。 ### 5.3.1 密碼重置鏈接請求表單示例 你需要為密碼重置請求表單 提供HTML視圖,該視圖文件應該放在`resources/views/auth/password.blade.php`,表單提供了一個輸入用戶郵箱地址的字段,從而允許用戶從郵件中訪問密碼重置鏈接: ~~~ <!-- resources/views/auth/password.blade.php --> <form method="POST" action="/password/email"> {!! csrf_field() !!} <div> Email <input type="email" name="email" value="{{ old('email') }}"> </div> <div> <button type="submit"> Send Password Reset Link </button> </div> </form> ~~~ 當一個用戶提交了重置密碼請求后,將會收到一封電子郵件,其中包含了一個鏈接,該鏈接指向`PasswordController`的`getReset`方法,你需要為該電子郵件創建一個視圖`resources/views/emails/password.blade.php`。該視圖將會獲取包含密碼重置令牌的`$token`變量,用于和用戶重置密碼請求進行匹配。下面是一個電子郵件視圖的例子: ~~~ <!-- resources/views/emails/password.blade.php --> Click here to reset your password: {{ url('password/reset/'.$token) }} ~~~ ### 5.3.2 密碼重置表單示例 當用戶點擊電子郵件中的鏈接來重置密碼時,需要提交一個密碼重置表單,該視圖位于`resources/views/auth/reset.blade.php`。 下面是一個密碼重置表單示例: ~~~ <!-- resources/views/auth/reset.blade.php --> <form method="POST" action="/password/reset"> {!! csrf_field() !!} <input type="hidden" name="token" value="{{ $token }}"> <div> <input type="email" name="email" value="{{ old('email') }}"> </div> <div> <input type="password" name="password"> </div> <div> <input type="password" name="password_confirmation"> </div> <div> <button type="submit"> Reset Password </button> </div> </form> ~~~ ### 5.4 重置密碼后 如果你已經定義好路由和視圖來重置用戶密碼,只需要在瀏覽器中訪問這些路由即可。框架自帶的`PasswordController`已經包含了發送密碼重置鏈接郵件以及更新數據庫中密碼的邏輯。 密碼被重置后,用戶將會自動登錄到應用并重定向到`/home`。你可以通過定義上`PasswordController`的`redirectTo`屬性來自定義post密碼重置跳轉鏈接: ~~~ protected $redirectTo = '/dashboard'; ~~~ > 注意:默認情況下,密碼重置令牌一小時內有效,你可以通過修改`config/auth.php`文件中的選項`reminder.expire`來改變有效時間。 ## 6、社會化登錄認證 Laravel中還可以使用[Laravel Socialite](https://github.com/laravel/socialite)通過OAuth提供者進行簡單、方便的認證,也就是社會化登錄,目前支持使用Facebook、Twitter、LinkedIn、GitHub和Bitbucket進行登錄認證。 要使用社會化登錄,需要在`composer.json`文件中添加依賴: ~~~ composer require laravel/socialite ~~~ ### 6.1 配置 安裝完社會化登錄庫后,在配置文件`config/app.php`中注冊`Laravel\Socialite\SocialiteServiceProvider`: ~~~ 'providers' => [ // 其它服務提供者... Laravel\Socialite\SocialiteServiceProvider::class, ], ~~~ 還要在`app`配置文件中添加`Socialite`門面到`aliases`數組: ~~~ 'Socialite' => Laravel\Socialite\Facades\Socialite::class, ~~~ 你還需要為應用使用的OAuth服務添加認證信息,這些認證信息位于配置文件`config/services.php`,而且鍵為`facebook`,?`twitter`,`linkedin`,?`google`,?`github`或`bitbucket`,這取決于應用需要的提供者。例如: ~~~ 'github' => [ 'client_id' => 'your-github-app-id', 'client_secret' => 'your-github-app-secret', 'redirect' => 'http://your-callback-url', ], ~~~ ### 6.2 基本使用 接下來,準備好認證用戶!你需要兩個路由:一個用于重定向用戶到OAuth提供者,另一個用戶獲取認證后來自提供者的回調。我們使用`Socialite`門面訪問Socialite?: ~~~ <?php namespace App\Http\Controllers; use Socialite; use Illuminate\Routing\Controller; class AuthController extends Controller{ /** * 將用戶重定向到GitHub認證頁面. * * @return Response */ public function redirectToProvider() { return Socialite::driver('github')->redirect(); } /** * 從GitHub獲取用戶信息. * * @return Response */ public function handleProviderCallback() { $user = Socialite::driver('github')->user(); // $user->token; } } ~~~ `redirect`方法將用戶發送到OAuth提供者,`user`方法讀取請求信息并從提供者中獲取用戶信息,在重定向用戶之前,你還可以在請求上使用`scope`方法設置”作用域”,該方法將會重寫已存在的所有作用域: ~~~ return Socialite::driver('github') ->scopes(['scope1', 'scope2'])->redirect(); ~~~ 當然,你需要定義路由到控制器方法: ~~~ Route::get('auth/github', 'Auth\AuthController@redirectToProvider'); Route::get('auth/github/callback', 'Auth\AuthController@handleProviderCallback'); ~~~ ### 6.2.1 獲取用戶信息 有了用戶實例之后,可以獲取用戶的更多詳情: ~~~ $user = Socialite::driver('github')->user(); // OAuth Two Providers $token = $user->token; // OAuth One Providers $token = $user->token; $tokenSecret = $user->tokenSecret; // All Providers $user->getId(); $user->getNickname(); $user->getName(); $user->getEmail(); $user->getAvatar(); ~~~ ## 7、添加自定義認證驅動 如果你沒有使用傳統的關系型數據庫存儲用戶信息,你需要使用自己的認證驅動擴展Laravel。我們使用Auth[門面](http://laravelacademy.org/post/97.html)上的`extend`方法來定義自定義的驅動,你需要在[服務提供者](http://laravelacademy.org/post/91.html)調用`extend`方法: ~~~ <?php namespace App\Providers; use Auth; use App\Extensions\RiakUserProvider; use Illuminate\Support\ServiceProvider; class AuthServiceProvider extends ServiceProvider{ /** * Perform post-registration booting of services. * * @return void */ public function boot() { Auth::extend('riak', function($app) { // 返回Illuminate\Contracts\Auth\UserProvider實例... return new RiakUserProvider($app['riak.connection']); }); } /** * 在容器中注冊綁定. * * @return void */ public function register() { // } } ~~~ 通過`extend`方法注冊驅動后,你可以在配置文件`config/auth.php`中切換到新的驅動。 ### 7.1 UserProvider契約 `Illuminate\Contracts\Auth\UserProvider`實現只負責從持久化存儲系統中獲取`Illuminate\Contracts\Auth\Authenticatable`實現,例如MySQL、Riak等等。這兩個接口允許Laravel認證機制繼續起作用而不管用戶數據如何存儲或者何種類來展現。 讓我們先看看`Illuminate\Contracts\Auth\UserProvider`[契約](http://laravelacademy.org/post/95.html): ~~~ <?php namespace Illuminate\Contracts\Auth; interface UserProvider { public function retrieveById($identifier); public function retrieveByToken($identifier, $token); public function updateRememberToken(Authenticatable $user, $token); public function retrieveByCredentials(array $credentials); public function validateCredentials(Authenticatable $user, array $credentials); } ~~~ `retrieveById`方法通常獲取一個代表用戶的鍵,例如MySQL數據中的自增ID。該方法獲取并返回匹配該ID的`Authenticatabl`實現。 `retrieveByToken`函數通過唯一標識和存儲在`remember_token`字段中的“記住我”令牌獲取用戶。和上一個方法一樣,該方法也返回`Authenticatabl`實現。 `updateRememberToken`方法使用新的`$token`更新`$user`的`remember_token`字段,新令牌可以是新生成的令牌(在登錄是選擇“記住我”被成功賦值)或者null(用戶退出)。 `retrieveByCredentials`方法在嘗試登錄系統時獲取傳遞給`Auth::attempt`方法的認證信息數組。該方法接下來去底層持久化存儲系統查詢與認證信息匹配的用戶,通常,該方法運行一個帶“where”條件($credentials[‘username’])的查詢。然后該方法返回`UserInterface`的實現。這個方法不做任何密碼校驗和認證。 `validateCredentials`方法比較給定`$user`和`$credentials`來認證用戶。例如,這個方法比較`$user->getAuthPassword()`字符串和經`Hash::make`處理的`$credentials['password']`。這個方法只驗證用戶認證信息并返回布爾值。 ### 7.2?Authenticatable契約 既然我們已經探索了`UserProvider`上的每一個方法,接下來讓我們看看`Authenticatable`。該提供者應該從`retrieveById`和`retrieveByCredentials`方法中返回接口實現: ~~~ <?php namespace Illuminate\Contracts\Auth; interface Authenticatable { public function getAuthIdentifier(); public function getAuthPassword(); public function getRememberToken(); public function setRememberToken($value); public function getRememberTokenName(); } ~~~ 這個接口很簡單,`getAuthIdentifier`方法返回用戶“主鍵”,在MySQL后臺中是ID,`getAuthPassword`返回經哈希處理的用戶密碼,這個接口允許認證系統處理任何用戶類,不管是你使用的是ORM還是存儲抽象層。默認情況下,Laravel自帶的`app`目錄下的`User`類實現了這個接口,所以你可以將這個類作為實現例子。 > 擴展閱讀1:[實例教程 —— 使用Laravel內置組件快速實現注冊登錄](http://laravelacademy.org/post/1258.html) > 擴展閱讀2:[實例教程 —— 使用Laravel內置組件快速實現密碼重置](http://laravelacademy.org/post/1290.html) > 擴展閱讀3:[實例教程 —— 使用Socialite實現GitHub登錄認證](http://laravelacademy.org/post/1305.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看