├── .gitignore ├── version.php ├── src ├── DcatAuthGoogle2FaServiceProvider.php ├── Models │ └── AdminUser.php └── Http │ ├── routes.php │ └── Controllers │ ├── Actions │ ├── UnbindRowAction.php │ └── BindRowAction.php │ ├── DcatAuthGoogle2FaUserController.php │ └── DcatAuthGoogle2FaAuthController.php ├── LICENSE ├── resources ├── lang │ ├── zh-CN │ │ └── dcat-auth-google-2fa.php │ ├── zh_CN │ │ └── dcat-auth-google-2fa.php │ └── en │ │ └── dcat-auth-google-2fa.php └── views │ └── login.blade.php ├── composer.json ├── updates └── 2021_08_21_120702_add_google_two_fa_secret_to_admin_users_table.php └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | phpunit.phar 3 | /vendor 4 | composer.phar 5 | composer.lock 6 | *.project 7 | .idea/ -------------------------------------------------------------------------------- /version.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'Dcat-Admin 登录 Google 2FA两步验证第一版', 6 | '2021_08_21_120702_add_google_two_fa_secret_to_admin_users_table.php', 7 | ], 8 | ]; 9 | -------------------------------------------------------------------------------- /src/DcatAuthGoogle2FaServiceProvider.php: -------------------------------------------------------------------------------- 1 | '两步验证码', 5 | '2fa_bind' => '绑定两步验证', 6 | '2fa_bind_confirm' => '确认要绑定该用户的两步验证吗?', 7 | '2fa_bind_success' => '绑定操作成功', 8 | '2fa_unbind' => '解绑两步验证', 9 | '2fa_unbind_confirm' => '确认要解绑该用户的两步验证吗?', 10 | '2fa_unbind_success' => '解绑操作成功', 11 | 'check_code_error' => '您输入的验证码不正确', 12 | 'google_2fa' => '两步验证', 13 | 'google_2fa_code' => '两步验证验证码', 14 | 'google_2fa_code_enable_help' => '请输入两步验证码,只有验证通过方可绑定', 15 | 'google_2fa_code_tips' => '请输入验证码(如有设置则必填)', 16 | 'google_2fa_code_disable_button' => '若要解绑两步验证,请将开关关闭', 17 | 'google_2fa_code_disable_help' => '请输入两步验证码,只有验证通过方可解绑', 18 | 'google_2fa_qrcode' => '两步验证二维码', 19 | 'google_2fa_qrcode_help' => '若要绑定两步验证,请扫描二维码', 20 | 'login_code_error' => '登录失败,您输入的验证码不正确', 21 | 'login_need_code' => '登录失败,请输入两步验证验证码', 22 | 'login_status_false' => '登录失败,您的账号已禁用', 23 | 'message' => '提示', 24 | 'status' => '账号状态', 25 | 'qrcode_service_tips' => '您需要安装二维码扩展包方可正常使用,访问网址查看说明。https://github.com/asundust/dcat-auth-google-2fa#%E9%87%8D%E8%A6%81%E8%AF%B4%E6%98%8E', 26 | ]; 27 | -------------------------------------------------------------------------------- /resources/lang/zh_CN/dcat-auth-google-2fa.php: -------------------------------------------------------------------------------- 1 | '两步验证码', 5 | '2fa_bind' => '绑定两步验证', 6 | '2fa_bind_confirm' => '确认要绑定该用户的两步验证吗?', 7 | '2fa_bind_success' => '绑定操作成功', 8 | '2fa_unbind' => '解绑两步验证', 9 | '2fa_unbind_confirm' => '确认要解绑该用户的两步验证吗?', 10 | '2fa_unbind_success' => '解绑操作成功', 11 | 'check_code_error' => '您输入的验证码不正确', 12 | 'google_2fa' => '两步验证', 13 | 'google_2fa_code' => '两步验证验证码', 14 | 'google_2fa_code_enable_help' => '请输入两步验证码,只有验证通过方可绑定', 15 | 'google_2fa_code_tips' => '请输入验证码(如有设置则必填)', 16 | 'google_2fa_code_disable_button' => '若要解绑两步验证,请将开关关闭', 17 | 'google_2fa_code_disable_help' => '请输入两步验证码,只有验证通过方可解绑', 18 | 'google_2fa_qrcode' => '两步验证二维码', 19 | 'google_2fa_qrcode_help' => '若要绑定两步验证,请扫描二维码', 20 | 'login_code_error' => '登录失败,您输入的验证码不正确', 21 | 'login_need_code' => '登录失败,请输入两步验证验证码', 22 | 'login_status_false' => '登录失败,您的账号已禁用', 23 | 'message' => '提示', 24 | 'status' => '账号状态', 25 | 'qrcode_service_tips' => '您需要安装二维码扩展包方可正常使用,访问网址查看说明。https://github.com/asundust/dcat-auth-google-2fa#%E9%87%8D%E8%A6%81%E8%AF%B4%E6%98%8E', 26 | ]; 27 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asundust/dcat-auth-google-2fa", 3 | "alias": "Auth Google 2FA两步验证", 4 | "description": "Dcat-Admin auth verification by Google 2FA / Dcat-Admin 登录 Google 2FA两步验证", 5 | "type": "library", 6 | "keywords": [ 7 | "dcat-admin", 8 | "extension", 9 | "google", 10 | "auth", 11 | "2fa", 12 | "login", 13 | "captcha" 14 | ], 15 | "homepage": "https://github.com/asundust/dcat-auth-google-2fa", 16 | "license": "MIT", 17 | "authors": [ 18 | { 19 | "name": "asundust", 20 | "email": "asundust@qq.com" 21 | } 22 | ], 23 | "require": { 24 | "php": ">=7.1.0", 25 | "dcat/laravel-admin": "~2.0", 26 | "pragmarx/google2fa-qrcode": "^2.0|^3.0" 27 | }, 28 | "autoload": { 29 | "psr-4": { 30 | "Asundust\\DcatAuthGoogle2Fa\\": "src/" 31 | } 32 | }, 33 | "extra": { 34 | "dcat-admin": "Asundust\\DcatAuthGoogle2Fa\\DcatAuthGoogle2FaServiceProvider", 35 | "laravel": { 36 | "providers": [ 37 | "Asundust\\DcatAuthGoogle2Fa\\DcatAuthGoogle2FaServiceProvider" 38 | ] 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Http/Controllers/Actions/UnbindRowAction.php: -------------------------------------------------------------------------------- 1 | where('id', $this->getKey())->update(['google_two_fa_secret' => null, 'google_two_fa_enable' => AdminUser::GOOGLE_TWO_FA_ENABLE_FALSE]); 26 | return $this->response()->success(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.2fa_unbind_success'))->refresh(); 27 | } 28 | 29 | 30 | /** 31 | * @return string[] 32 | */ 33 | public function confirm() 34 | { 35 | return [ 36 | DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.message'), 37 | DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.2fa_unbind_confirm'), 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /updates/2021_08_21_120702_add_google_two_fa_secret_to_admin_users_table.php: -------------------------------------------------------------------------------- 1 | config('database.users_table'), function (Blueprint $table) { 22 | if (Schema::hasColumns($this->config('database.users_table'), ['remember_token'])) { 23 | $table->string('google_two_fa_secret', 32)->nullable()->after('remember_token'); 24 | } else { 25 | $table->string('google_two_fa_secret', 32)->nullable(); 26 | } 27 | $table->boolean('google_two_fa_enable')->default(0)->index()->after('google_two_fa_secret'); 28 | $table->boolean('status')->default(1)->index()->after('google_two_fa_enable'); 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::table($this->config('database.users_table'), function (Blueprint $table) { 40 | $table->dropColumn('google_two_fa_secret'); 41 | $table->dropColumn('google_two_fa_enable'); 42 | $table->dropColumn('status'); 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Dcat-Admin 登录 Google 2FA两步验证 / Dcat-Admin auth verification by Google 2FA 2 | ====== 3 | 4 | ![StyleCI build status](https://github.styleci.io/repos/686662708/shield) 5 | 6 | Dcat-Admin 登录 Google 2FA两步验证 7 | 8 | ![image](https://github.com/asundust/auth-captcha/assets/6573979/9d3283ea-2cb4-4ce1-9eff-10ce0b82d41e) 9 | 10 | ### 重要说明!!! 11 | 12 | - 本包依赖于[pragmarx/google2fa-qrcode](https://packagist.org/packages/pragmarx/google2fa-qrcode),该包的二维码依赖是可选扩展包,默认支持[bacon/bacon-qr-code](https://packagist.org/packages/bacon/bacon-qr-code)、[chillerlan/php-qrcode](https://packagist.org/packages/chillerlan/php-qrcode)扩展,需要手动安装,为了兼容性考虑,请选择下方的其中一个扩展安装即可。 13 | - 以上参见说明:[#3](https://github.com/asundust/dcat-auth-google-2fa/issues/3) [https://github.com/antonioribeiro/google2fa-qrcode#built-in-qrcode-rendering-services](https://github.com/antonioribeiro/google2fa-qrcode#built-in-qrcode-rendering-services) 14 | ``` 15 | composer require bacon/bacon-qr-code 16 | ``` 17 | ``` 18 | composer require chillerlan/php-qrcode 19 | ``` 20 | 21 | ### 安装 22 | 23 | ``` 24 | composer require asundust/dcat-auth-google-2fa 25 | ``` 26 | 27 | ### 说明 28 | 29 | - 本应用暂不支持Dact-Admin`1.*`版本,也不考虑支持。 30 | - Dact-Admin`1.*`版本可以使用[https://github.com/changzhong/extension-google-authenticator](https://github.com/changzhong/extension-google-authenticator) 31 | - 本项目也是因为看到目前插件空缺才补上,代码参考上述项目。 32 | 33 | ### 主要功能 34 | 35 | - 登录页谷歌2FA认证 36 | - 支持自助绑定解绑 37 | - 管理员可以绑定解绑 38 | - 支持简体中文及英语 39 | 40 | ### 支持 41 | 42 | 如果觉得这个项目帮你节约了时间,不妨支持一下呗! 43 | 44 | ![alipay](https://user-images.githubusercontent.com/6573979/91679916-2c4df500-eb7c-11ea-98a7-ab740ddda77d.png) 45 | ![wechat](https://user-images.githubusercontent.com/6573979/91679913-2b1cc800-eb7c-11ea-8915-eb0eced94aee.png) 46 | 47 | ### License 48 | 49 | [The MIT License (MIT)](https://opensource.org/licenses/MIT) 50 | -------------------------------------------------------------------------------- /resources/lang/en/dcat-auth-google-2fa.php: -------------------------------------------------------------------------------- 1 | 'Google 2FA Code', 5 | '2fa_bind' => 'Binding Google 2FA', 6 | '2fa_bind_confirm' => 'Are you sure you want to bind the user\'s Google 2FA?', 7 | '2fa_bind_success' => 'The binding operation was successful', 8 | '2fa_unbind' => 'Unbinding Google 2FA', 9 | '2fa_unbind_confirm' => 'Are you sure you want to unbind the user\'s Google 2FA?', 10 | '2fa_unbind_success' => 'The unbinding operation was successful', 11 | 'check_code_error' => 'The Google 2FA code you entered is incorrect', 12 | 'google_2fa' => 'Google 2FA', 13 | 'google_2fa_code' => 'Google 2FA code', 14 | 'google_2fa_code_enable_help' => 'Please enter the Google 2FA code, Only after verification is passed can you bind it', 15 | 'google_2fa_code_disable_button' => 'To unbind Google 2FA, please turn off the switch', 16 | 'google_2fa_code_disable_help' => 'Please enter the Google 2FA code, Only after verification is passed can the binding be unbound', 17 | 'google_2fa_code_tips' => 'Please enter the Google 2FA code (Required if set)', 18 | 'google_2fa_qrcode' => 'Google 2FA of QR code', 19 | 'google_2fa_qrcode_help' => 'To bind Google 2FA, please scan the QR code', 20 | 'login_code_error' => 'Login failed, the Google 2FA code is incorrect', 21 | 'login_need_code' => 'Login failed, please enter the Google 2FA code', 22 | 'login_status_false' => 'Login failed, your account has been disabled', 23 | 'message' => 'Message', 24 | 'status' => 'Account status', 25 | 'qrcode_service_tips' => 'You need to install a QR code service package or assign yourself the service to be used. Visit the website to view instructions. https://github.com/asundust/dcat-auth-google-2fa#%E9%87%8D%E8%A6%81%E8%AF%B4%E6%98%8E', 26 | ]; 27 | -------------------------------------------------------------------------------- /src/Http/Controllers/Actions/BindRowAction.php: -------------------------------------------------------------------------------- 1 | generateSecretKey(32); 34 | /* @var AdminUser $user */ 35 | $user = AdminUser::query()->find($this->getKey()); 36 | $user->google_two_fa_secret = $secret; 37 | $user->google_two_fa_enable = AdminUser::GOOGLE_TWO_FA_ENABLE_TRUE; 38 | $user->save(); 39 | return $this->response()->success(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.2fa_bind_success'))->refresh(); 40 | } 41 | 42 | /** 43 | * @return string[] 44 | */ 45 | public function confirm() 46 | { 47 | return [ 48 | DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.message'), 49 | DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.2fa_bind_confirm'), 50 | ]; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /resources/views/login.blade.php: -------------------------------------------------------------------------------- 1 | 28 | 29 |
30 |
31 | 34 |
35 | 153 |
154 |
155 |
156 | 157 | 165 | -------------------------------------------------------------------------------- /src/Http/Controllers/DcatAuthGoogle2FaUserController.php: -------------------------------------------------------------------------------- 1 | column('id', trans('id'))->sortable(); 23 | $grid->column('username', trans('admin.username')); 24 | $grid->column('name', trans('admin.name')); 25 | 26 | $grid->column('status', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.status')) 27 | ->bool(); 28 | $grid->column('google_two_fa_enable', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa')) 29 | ->bool() 30 | ->if(function () { 31 | /* @var AdminUser $this */ 32 | return $this->google_two_fa_enable; 33 | }) 34 | ->qrcode(function () { 35 | /* @var AdminUser $this */ 36 | $google2fa = new Google2FA(); 37 | return $google2fa->getQRCodeUrl(config('admin.name'), $this->username, $this->google_two_fa_secret); 38 | }, 200, 200); 39 | 40 | if (config('admin.permission.enable')) { 41 | $grid->column('roles', trans('admin.roles'))->pluck('name')->label('primary', 3); 42 | 43 | $permissionModel = config('admin.database.permissions_model'); 44 | $roleModel = config('admin.database.roles_model'); 45 | $nodes = (new $permissionModel())->allNodes(); 46 | $grid->column('permissions', trans('admin.permission')) 47 | ->if(function () { 48 | return !$this['roles']->isEmpty(); 49 | }) 50 | ->showTreeInDialog(function (Grid\Displayers\DialogTree $tree) use (&$nodes, $roleModel) { 51 | $tree->nodes($nodes); 52 | 53 | foreach (array_column($this['roles']->toArray(), 'slug') as $slug) { 54 | if ($roleModel::isAdministrator($slug)) { 55 | $tree->checkAll(); 56 | } 57 | } 58 | }) 59 | ->else() 60 | ->display(''); 61 | } 62 | 63 | $grid->column('created_at', trans('admin.created_at')); 64 | $grid->column('updated_at', trans('admin.updated_at'))->sortable(); 65 | 66 | $grid->quickSearch(['id', 'name', 'username']); 67 | 68 | $grid->showQuickEditButton(); 69 | $grid->enableDialogCreate(); 70 | $grid->showColumnSelector(); 71 | $grid->disableEditButton(); 72 | 73 | $grid->actions(function (Grid\Displayers\Actions $actions) { 74 | if ($actions->getKey() == AdminUser::DEFAULT_ID) { 75 | $actions->disableDelete(); 76 | } 77 | if ($actions->row['google_two_fa_enable']) { 78 | $actions->append(new UnbindRowAction()); 79 | } else { 80 | $actions->append(new BindRowAction()); 81 | } 82 | }); 83 | }); 84 | } 85 | 86 | protected function detail($id) 87 | { 88 | return Show::make($id, Administrator::with(['roles']), function (Show $show) { 89 | $show->field('id', trans('id')); 90 | $show->field('username', trans('admin.username')); 91 | $show->field('name', trans('admin.name')); 92 | 93 | $show->field('status', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.status')) 94 | ->bool(); 95 | $show->field('google_two_fa_enable', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa')) 96 | ->bool(); 97 | 98 | $show->field('avatar', __('admin.avatar'))->image(); 99 | 100 | if (config('admin.permission.enable')) { 101 | $show->field('roles', trans('admin.roles'))->as(function ($roles) { 102 | if (!$roles) { 103 | return []; 104 | } 105 | 106 | return collect($roles)->pluck('name'); 107 | })->label(); 108 | 109 | $show->field('permissions', trans('admin.permission'))->unescape()->as(function () { 110 | $roles = $this['roles']->toArray(); 111 | 112 | $permissionModel = config('admin.database.permissions_model'); 113 | $roleModel = config('admin.database.roles_model'); 114 | $permissionModel = new $permissionModel(); 115 | $nodes = $permissionModel->allNodes(); 116 | 117 | $tree = Tree::make($nodes); 118 | 119 | $isAdministrator = false; 120 | foreach (array_column($roles, 'slug') as $slug) { 121 | if ($roleModel::isAdministrator($slug)) { 122 | $tree->checkAll(); 123 | $isAdministrator = true; 124 | } 125 | } 126 | 127 | if (!$isAdministrator) { 128 | $keyName = $permissionModel->getKeyName(); 129 | $tree->check( 130 | $roleModel::getPermissionId(array_column($roles, $keyName))->flatten() 131 | ); 132 | } 133 | 134 | return $tree->render(); 135 | }); 136 | } 137 | 138 | $show->field('created_at', trans('admin.created_at')); 139 | $show->field('updated_at', trans('admin.updated_at')); 140 | }); 141 | } 142 | 143 | public function form() 144 | { 145 | return Form::make(Administrator::with(['roles']), function (Form $form) { 146 | $userTable = config('admin.database.users_table'); 147 | 148 | $connection = config('admin.database.connection'); 149 | 150 | $id = $form->getKey(); 151 | 152 | $form->display('id', 'ID'); 153 | 154 | $form->text('username', trans('admin.username')) 155 | ->required() 156 | ->creationRules(['required', "unique:$connection.$userTable"]) 157 | ->updateRules(['required', "unique:$connection.$userTable,username,$id"]); 158 | $form->text('name', trans('admin.name'))->required(); 159 | $form->image('avatar', trans('admin.avatar'))->autoUpload(); 160 | $form->switch('status', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.status'))->default(AdminUser::STATUS_TRUE); 161 | $form->switch('google_two_fa_enable', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa'))->default(AdminUser::GOOGLE_TWO_FA_ENABLE_FALSE); 162 | 163 | if ($id) { 164 | $form->password('password', trans('admin.password')) 165 | ->minLength(5) 166 | ->maxLength(20) 167 | ->customFormat(function () { 168 | return ''; 169 | }); 170 | } else { 171 | $form->password('password', trans('admin.password')) 172 | ->required() 173 | ->minLength(5) 174 | ->maxLength(20); 175 | } 176 | 177 | $form->password('password_confirmation', trans('admin.password_confirmation'))->same('password'); 178 | 179 | $form->ignore(['password_confirmation']); 180 | 181 | if (config('admin.permission.enable')) { 182 | $form->multipleSelect('roles', trans('admin.roles')) 183 | ->options(function () { 184 | $roleModel = config('admin.database.roles_model'); 185 | 186 | return $roleModel::all()->pluck('name', 'id'); 187 | }) 188 | ->customFormat(function ($v) { 189 | return array_column($v, 'id'); 190 | }); 191 | } 192 | 193 | $form->display('created_at', trans('admin.created_at')); 194 | $form->display('updated_at', trans('admin.updated_at')); 195 | 196 | if ($id == AdminUser::DEFAULT_ID) { 197 | $form->disableDeleteButton(); 198 | } 199 | })->saving(function (Form $form) { 200 | /* @var Form|AdminUser $form */ 201 | if ($form->password && $form->model()->get('password') != $form->password) { 202 | $form->password = bcrypt($form->password); 203 | } 204 | 205 | if (!$form->password) { 206 | $form->deleteInput('password'); 207 | } 208 | 209 | if ($form->google_two_fa_enable == AdminUser::GOOGLE_TWO_FA_ENABLE_TRUE) { 210 | $form->google_two_fa_secret = (new Google2FA())->generateSecretKey(32); 211 | } else { 212 | $form->google_two_fa_secret = null; 213 | } 214 | }); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/Http/Controllers/DcatAuthGoogle2FaAuthController.php: -------------------------------------------------------------------------------- 1 | view = DcatAuthGoogle2FaServiceProvider::instance()->getName() . '::login'; 31 | } 32 | 33 | /** 34 | * @param Request $request 35 | * 36 | * @return JsonResponse|RedirectResponse|Response 37 | * @throws IncompatibleWithGoogleAuthenticatorException 38 | * @throws InvalidCharactersException 39 | * @throws SecretKeyTooShortException 40 | */ 41 | public function postLogin(Request $request) 42 | { 43 | $credentials = $request->only([$this->username(), 'password']); 44 | $remember = (bool)$request->input('remember', false); 45 | 46 | /** @var \Illuminate\Validation\Validator $validator */ 47 | $validator = Validator::make($credentials, [ 48 | $this->username() => 'required', 49 | 'password' => 'required', 50 | ]); 51 | 52 | if ($validator->fails()) { 53 | return $this->validationErrorsResponse($validator); 54 | } 55 | 56 | $validatorCode = Validator::make($request->only(['google_2fa_code']), [ 57 | 'google_2fa_code' => 'nullable|numeric|digits:6', 58 | ], [], [ 59 | 'google_2fa_code' => DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.2fa_code'), 60 | ]); 61 | 62 | if ($validatorCode->fails()) { 63 | return $this->validationErrorsResponse($validatorCode); 64 | } 65 | 66 | if ($this->guard()->attempt($credentials, $remember)) { 67 | /* @var AdminUser $user */ 68 | $user = Admin::user(); 69 | 70 | if ($user->status != AdminUser::STATUS_TRUE) { 71 | $this->guard()->logout(); 72 | return $this->response() 73 | ->error(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.login_status_false')) 74 | ->send(); 75 | } 76 | 77 | if ($user->google_two_fa_enable == AdminUser::GOOGLE_TWO_FA_ENABLE_TRUE) { 78 | $google2faCode = $request->input('google_2fa_code'); 79 | if (!$google2faCode) { 80 | $this->guard()->logout(); 81 | return $this 82 | ->response() 83 | ->withValidation(new MessageBag(['google_2fa_code' => [DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.login_need_code')]])) 84 | ->send(); 85 | } 86 | if (!(new Google2FA())->verifyKey($user->google_two_fa_secret, $google2faCode)) { 87 | $this->guard()->logout(); 88 | return $this 89 | ->response() 90 | ->withValidation(new MessageBag(['google_2fa_code' => [DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.login_code_error')]])) 91 | ->send(); 92 | } 93 | } 94 | 95 | return $this->sendLoginResponse($request); 96 | } 97 | 98 | return $this->validationErrorsResponse([ 99 | $this->username() => $this->getFailedLoginMessage(), 100 | ]); 101 | } 102 | 103 | /** 104 | * @return Form 105 | */ 106 | protected function settingForm() 107 | { 108 | return new Form(new Administrator(), function (Form $form) { 109 | $form->action(admin_url('auth/setting')); 110 | 111 | $form->disableCreatingCheck(); 112 | $form->disableEditingCheck(); 113 | $form->disableViewCheck(); 114 | 115 | $form->tools(function (Form\Tools $tools) { 116 | $tools->disableView(); 117 | $tools->disableDelete(); 118 | }); 119 | 120 | $form->display('username', trans('admin.username')); 121 | $form->text('name', trans('admin.name'))->required(); 122 | $form->image('avatar', trans('admin.avatar'))->autoUpload(); 123 | 124 | $form->password('old_password', trans('admin.old_password')); 125 | 126 | $form->password('password', trans('admin.password')) 127 | ->minLength(5) 128 | ->maxLength(20) 129 | ->customFormat(function ($v) { 130 | if ($v == $this['password']) { 131 | return ''; 132 | } 133 | 134 | return $v; 135 | }); 136 | $form->password('password_confirmation', trans('admin.password_confirmation'))->same('password'); 137 | 138 | /* @var AdminUser $user */ 139 | $user = Admin::user(); 140 | if ($user->google_two_fa_enable) { 141 | $form->switch('google_two_fa_enable', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa')) 142 | ->help(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_code_disable_button')); 143 | $form->text('google_2fa_code', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_code')) 144 | ->help(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_code_disable_help')); 145 | $form->hidden('google_two_fa_secret'); 146 | $form->hidden('current_google_two_fa_enable')->value('enable'); 147 | } else { 148 | $google2fa = new \PragmaRX\Google2FAQRCode\Google2FA(); 149 | if (!$google2fa->getQrCodeService()) { 150 | throw new MissingQrCodeServiceException( 151 | DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.qrcode_service_tips') 152 | ); 153 | } 154 | $googleTwoFaSecret = $google2fa->generateSecretKey(32); 155 | $qrcode = $google2fa->getQRCodeInline(config('admin.name'), $user->username, $googleTwoFaSecret); 156 | $form->display('google_2fa_qrcode', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_qrcode')) 157 | ->help(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_qrcode_help')) 158 | ->width(4) 159 | ->with(function () use ($qrcode, $google2fa) { 160 | if (strpos($qrcode, ';base64,') !== false) { 161 | return ''; 162 | } else { 163 | return $qrcode; 164 | } 165 | }); 166 | $form->text('google_2fa_code', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_code')) 167 | ->help(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_code_enable_help')); 168 | $form->hidden('google_two_fa_secret')->value($googleTwoFaSecret); 169 | $form->hidden('google_two_fa_enable'); 170 | $form->hidden('current_google_two_fa_enable')->value('disable'); 171 | } 172 | 173 | $form->ignore(['password_confirmation', 'old_password']); 174 | 175 | $form->saving(function (Form $form) { 176 | /* @var Form|AdminUser $form */ 177 | /* @var AdminUser $adminUser */ 178 | $adminUser = $form->model(); 179 | if ($form->password && $adminUser->password != $form->password) { 180 | $form->password = bcrypt($form->password); 181 | } 182 | 183 | if (!$form->password) { 184 | $form->deleteInput('password'); 185 | } 186 | 187 | if ($form->input('current_google_two_fa_enable') == 'enable') { 188 | if (!$form->google_two_fa_enable) { 189 | $google2faCode = $form->input('google_2fa_code'); 190 | if (!$google2faCode) { 191 | return $form->response()->error(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.check_code_error')); 192 | } 193 | $google2fa = new Google2FA(); 194 | if (!$google2fa->verifyKey($adminUser->google_two_fa_secret, $google2faCode)) { 195 | return $form->response()->error(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.check_code_error')); 196 | } 197 | $form->google_two_fa_enable = AdminUser::GOOGLE_TWO_FA_ENABLE_FALSE; 198 | $form->google_two_fa_secret = null; 199 | } 200 | } else { 201 | $googleTwoFaSecret = $form->google_two_fa_secret; 202 | $google2faCode = $form->input('google_2fa_code'); 203 | if ($googleTwoFaSecret) { 204 | if ($google2faCode) { 205 | $google2fa = new Google2FA(); 206 | if (!$google2fa->verifyKey($form->google_two_fa_secret, $google2faCode)) { 207 | return $form->response()->error(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.check_code_error')); 208 | } 209 | $form->google_two_fa_enable = AdminUser::GOOGLE_TWO_FA_ENABLE_TRUE; 210 | } else { 211 | $form->google_two_fa_secret = null; 212 | } 213 | } 214 | } 215 | $form->deleteInput(['google_2fa_code', 'current_google_two_fa_enable']); 216 | }); 217 | 218 | $form->saved(function (Form $form) { 219 | return $form 220 | ->response() 221 | ->success(trans('admin.update_succeeded')) 222 | ->redirect('auth/setting'); 223 | }); 224 | }); 225 | } 226 | } 227 | --------------------------------------------------------------------------------