Przeglądaj źródła

完成了Geetest极验验证 & 优化了系统设置切换栏的CSS样式

MIse 7 lat temu
rodzic
commit
251d637185

+ 20 - 6
app/Http/Controllers/AuthController.php

@@ -58,12 +58,26 @@ class AuthController extends Controller
             }
 
             // 是否校验验证码
-            if (self::$systemConfig['is_captcha']) {
-                if (!Captcha::check($captcha)) {
-                    Session::flash('errorMsg', '验证码错误,请重新输入');
-
-                    return Redirect::back()->withInput();
-                }
+            switch (self::$systemConfig['is_captcha']) {
+                case 1:
+                    // Default Captcha
+                    if (!Captcha::check($captcha)) {
+                        Session::flash('errorMsg', '验证码错误,请重新输入');
+                        return Redirect::back()->withInput();
+                    }
+                    break;
+                case 2:
+                    // Geetest
+                    // return Redirect::back()->withInput();
+                    echo 'Geetest';
+                    break;
+                case 3:
+                    // Google reCAPTCHA
+                    echo 'Google reCAPTCHA';
+                    break;
+                default:
+                    # nothing..
+                    break;
             }
 
             // 验证账号并创建会话

+ 32 - 0
app/Http/Controllers/CaptchaController.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Response;
+use Geetest;
+
+/**
+ * 验证码控制器
+ * Class CaptchaController
+
+ * @package App\Http\Controllers
+ */
+class CaptchaController extends Controller 
+{
+    /**
+     * @param Request $request
+     */
+    public function geetestPostValidate(Request $request)
+    {   
+        $result = $this->validate($request, [
+            'geetest_challenge' => 'required|geetest'
+        ], [
+            'geetest' => config('geetest.server_fail_alert')
+        ]);
+        
+        if ($result) {
+            return Response::json(['status' => 'success', 'data' => '', 'message' => '服务器二次校验通过']);
+        }
+    }
+} 

+ 1 - 0
composer.json

@@ -8,6 +8,7 @@
         "php": "^7.1.3",
         "barryvdh/laravel-ide-helper": "^2.5",
         "fideloper/proxy": "^4.0",
+        "germey/geetest": "^3.0",
         "guzzlehttp/guzzle": "^6.3",
         "ipip/db": "^1.0",
         "itbdw/ip-database": "^2.0",

+ 59 - 2
composer.lock

@@ -1,10 +1,10 @@
 {
     "_readme": [
         "This file locks the dependencies of your project to a known state",
-        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "content-hash": "548690c9d667e05f6589c9f975b31819",
+    "content-hash": "bbe1dbabbde863237148a7122779f9cd",
     "packages": [
         {
             "name": "barryvdh/laravel-ide-helper",
@@ -978,6 +978,63 @@
             ],
             "time": "2019-01-10T14:06:47+00:00"
         },
+        {
+            "name": "germey/geetest",
+            "version": "v3.0.7",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Germey/LaravelGeetest.git",
+                "reference": "311e9b4e496b4e44cc570f29a2e17028a3454652"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Germey/LaravelGeetest/zipball/311e9b4e496b4e44cc570f29a2e17028a3454652",
+                "reference": "311e9b4e496b4e44cc570f29a2e17028a3454652",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://dl.laravel-china.org/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "laravel/framework": "5.*",
+                "php": ">=5.6.0"
+            },
+            "require-dev": {
+                "mockery/mockery": "dev-master",
+                "phpunit/phpunit": "~4.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.1-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Germey\\Geetest\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Germey",
+                    "email": "[email protected]"
+                }
+            ],
+            "description": "Geetest Package for Laravel5",
+            "keywords": [
+                "Germey",
+                "geetest",
+                "laravel"
+            ],
+            "time": "2018-07-12T12:06:28+00:00"
+        },
         {
             "name": "guzzlehttp/guzzle",
             "version": "6.3.3",

+ 2 - 1
config/app.php

@@ -150,6 +150,7 @@ return [
         /*
          * Package Service Providers...
          */
+        Germey\Geetest\GeetestServiceProvider::class,  // Geetest Service
 
         /*
          * Application Service Providers...
@@ -210,7 +211,7 @@ return [
         'Captcha'      => Mews\Captcha\Facades\Captcha::class,
         'Agent'        => Jenssegers\Agent\Facades\Agent::class,
         'Purifier'     => Mews\Purifier\Facades\Purifier::class,
-
+        'Geetest' => Germey\Geetest\Geetest::class,
     ],
 
 ];

+ 92 - 0
config/geetest.php

@@ -0,0 +1,92 @@
+<?php
+return [
+
+	/*
+	|--------------------------------------------------------------------------
+	| Config Language
+	|--------------------------------------------------------------------------
+	|
+	| Here you can config your yunpian api key from yunpian provided.
+	|
+	| Options: ['zh-cn', 'zh-tw', 'en', 'ja', 'ko']
+	|
+	*/
+	'lang' => 'zh-cn',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Config Geetest Id
+	|--------------------------------------------------------------------------
+	|
+	| Here you can config your yunpian api key from yunpian provided.
+	|
+	*/
+    'id' => env('GEETEST_ID'),
+
+
+	/*
+	|--------------------------------------------------------------------------
+	| Config Geetest Key
+	|--------------------------------------------------------------------------
+	|
+	| Here you can config your yunpian api key from yunpian provided.
+	|
+	*/
+    'key' => env('GEETEST_KEY'),
+
+	/*
+	|--------------------------------------------------------------------------
+	| Config Geetest URL
+	|--------------------------------------------------------------------------
+	|
+	| Here you can config your geetest url for ajax validation.
+	|
+	*/
+	'url' => '/geetest',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Config Geetest Protocol
+	|--------------------------------------------------------------------------
+	|
+	| Here you can config your geetest url for ajax validation.
+	| 
+	| Options: http or https
+	|
+	*/
+	'protocol' => 'http',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Config Geetest Product
+	|--------------------------------------------------------------------------
+	|
+	| Here you can config your geetest url for ajax validation.
+	| 
+	| Options: float, popup, custom, bind
+	|
+	*/
+	'product' => 'bind',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Config Client Fail Alert Text
+	|--------------------------------------------------------------------------
+	|
+	| Here you can config the alert text when it failed in client.
+	|
+	*/
+	'client_fail_alert' => '请正确完成验证码操作',
+
+	/*
+	|--------------------------------------------------------------------------
+	| Config Server Fail Alert
+	|--------------------------------------------------------------------------
+	|
+	| Here you can config the alert text when it failed in server (two factor validation).
+	|
+	*/
+	'server_fail_alert' => '验证码校验失败',
+
+
+];

+ 3 - 3
public/assets/global/css/components-rounded.css

@@ -13112,7 +13112,7 @@ Custom tabs
   margin: 0px; }
   .tabbable-line > .nav-tabs > li {
     margin: 0;
-    border-bottom: 4px solid transparent; }
+    border-bottom: 4px solid transparent !important; }
     .tabbable-line > .nav-tabs > li > a {
       background: none !important;
       border: 0;
@@ -13124,7 +13124,7 @@ Custom tabs
         color: #a6a6a6; }
     .tabbable-line > .nav-tabs > li.active {
       background: none;
-      border-bottom: 4px solid #36c6d3;
+      border-bottom: 4px solid #36c6d3 !important;
       position: relative; }
       .tabbable-line > .nav-tabs > li.active > a {
         border: 0;
@@ -13133,7 +13133,7 @@ Custom tabs
           color: #404040; }
     .tabbable-line > .nav-tabs > li.open, .tabbable-line > .nav-tabs > li:hover {
       background: none;
-      border-bottom: 4px solid #9fe4ea; }
+      border-bottom: 4px solid #9fe4ea !important; }
       .tabbable-line > .nav-tabs > li.open > a, .tabbable-line > .nav-tabs > li:hover > a {
         border: 0;
         background: none !important;

Plik diff jest za duży
+ 0 - 0
public/assets/global/css/components-rounded.min.css


+ 149 - 16
resources/views/admin/system.blade.php

@@ -49,6 +49,16 @@
                                         <li>
                                             <a href="#tab_10" data-toggle="tab"> 支付宝当面付 </a>
                                         </li>
+                                        @if (\App\Components\Helpers::systemConfig()['is_captcha'] == 2)
+                                        <li>
+                                            <a href="#tab_geetest" data-toggle="tab"> 极验验证 </a>
+                                        </li>
+                                        @endif
+                                        @if (\App\Components\Helpers::systemConfig()['is_captcha'] == 3)
+                                        <li>
+                                            <a href="#tab_googleCaptcha" data-toggle="tab"> Google验证 </a>
+                                        </li>
+                                        @endif
                                     </ul>
                                 </div>
                                 <div class="portlet-body">
@@ -121,7 +131,12 @@
                                                         <div class="col-md-6 col-sm-6 col-xs-12">
                                                             <label for="is_captcha" class="col-md-3 control-label">验证码</label>
                                                             <div class="col-md-9">
-                                                                <input type="checkbox" class="make-switch" @if($is_captcha) checked @endif id="is_captcha" data-on-color="success" data-off-color="danger" data-on-text="启用" data-off-text="关闭">
+                                                                <select id="is_captcha" class="form-control select2" name="is_captcha">
+                                                                    <option value="0" @if($is_captcha == '0') selected @endif>关闭</option>
+                                                                    <option value="1" @if($is_captcha == '1') selected @endif>普通验证码</option>
+                                                                    <option value="2" @if($is_captcha == '2') selected @endif>Geetest 极验</option>
+                                                                    <option value="3" @if($is_captcha == '3') selected @endif>Google reCAPTCHA</option>
+                                                                </select>
                                                                 <span class="help-block"> 启用后登录、注册需要输入验证码 </span>
                                                             </div>
                                                         </div>
@@ -995,6 +1010,92 @@
                                                 </div>
                                             </form>
                                         </div>
+                                        <div class="tab-pane" id="tab_geetest">
+                                            <form action="#" method="post" class="form-horizontal">
+                                                <div class="portlet-body">
+                                                    <div class="form-group">
+                                                        <div class="col-md-6 col-sm-6 col-xs-12">
+                                                            <label for="alipay_private_key"
+                                                            class="col-md-3 control-label">ID</label>
+                                                            <div class="col-md-9">
+                                                                <div class="input-group">
+                                                                    <input class="form-control" type="text" name="geetest_id" value="{{$geetest_id}}" id="geetest_id"/>
+                                                                    <span class="input-group-btn">
+                                                                        <button class="btn btn-success" type="button" onclick="setGeetestId()">修改</button>
+                                                                    </span>
+                                                                </div>
+                                                                <span class="help-block"> 本功能需要 <a href="https://auth.geetest.com/login/" target="_blank">极验后台</a> 申请权限及应用 </span>
+                                                            </div>
+                                                        </div>
+                                                        <div class="col-md-6 col-sm-6 col-xs-12">
+                                                            <label for="alipay_public_key"
+                                                                   class="col-md-3 control-label">KEY</label>
+                                                            <div class="col-md-9">
+                                                                <div class="input-group">
+                                                                    <input class="form-control" type="text" name="geetest_key" value="{{$geetest_key}}" id="geetest_key"/>
+                                                                    <span class="input-group-btn">
+                                                                    <button class="btn btn-success" type="button" onclick="setGeetestKey()">修改</button>
+                                                                </span>
+                                                                </div>
+                                                            </div>
+                                                        </div>
+                                                    </div>
+                                                </div>
+                                            </form>
+                                        </div>
+                                        <div class="tab-pane" id="tab_googleCaptcha">
+                                            <form action="#" method="post" class="form-horizontal">
+                                                <div class="portlet-body">
+                                                    <div class="form-group">
+                                                        <div class="col-md-6 col-sm-6 col-xs-12">
+                                                            <label for="is_f2fpay"
+                                                                   class="col-md-3 control-label">本功能</label>
+                                                            <div class="col-md-9">
+                                                                <input type="checkbox" class="make-switch" @if($is_f2fpay) checked @endif id="is_f2fpay" data-on-color="success" data-off-color="danger" data-on-text="启用" data-off-text="关闭">
+                                                                <span class="help-block"> 本功能需要 <a href="https://open.alipay.com/platform/home.htm" target="_blank">蚂蚁金服开放平台</a> 申请权限及应用 </span>
+                                                            </div>
+                                                        </div>
+                                                        <div class="col-md-6 col-sm-6 col-xs-12">
+                                                            <label for="alipay_partner" class="col-md-3 control-label">应用ID</label>
+                                                            <div class="col-md-9">
+                                                                <div class="input-group">
+                                                                    <input class="form-control" type="text" name="f2fpay_app_id" value="{{$f2fpay_app_id}}" id="f2fpay_app_id"/>
+                                                                    <span class="input-group-btn">
+                                                                        <button class="btn btn-success" type="button" onclick="setF2fpayAppId()">修改</button>
+                                                                    </span>
+                                                                </div>
+                                                            </div>
+                                                        </div>
+                                                    </div>
+                                                    <div class="form-group">
+                                                        <div class="col-md-6 col-sm-6 col-xs-12">
+                                                            <label for="alipay_private_key"
+                                                                   class="col-md-3 control-label">RSA私钥</label>
+                                                            <div class="col-md-9">
+                                                                <div class="input-group">
+                                                                    <input class="form-control" type="text" name="f2fpay_private_key" value="{{$f2fpay_private_key}}" id="f2fpay_private_key"/>
+                                                                    <span class="input-group-btn">
+                                                                        <button class="btn btn-success" type="button" onclick="setF2fpayPrivateKey()">修改</button>
+                                                                    </span>
+                                                                </div>
+                                                            </div>
+                                                        </div>
+                                                        <div class="col-md-6 col-sm-6 col-xs-12">
+                                                            <label for="alipay_public_key"
+                                                                   class="col-md-3 control-label">RSA公钥</label>
+                                                            <div class="col-md-9">
+                                                                <div class="input-group">
+                                                                    <input class="form-control" type="text" name="f2fpay_public_key" value="{{$f2fpay_public_key}}" id="f2fpay_public_key"/>
+                                                                    <span class="input-group-btn">
+                                                                    <button class="btn btn-success" type="button" onclick="setF2fpayPublicKey()">修改</button>
+                                                                </span>
+                                                                </div>
+                                                            </div>
+                                                        </div>
+                                                    </div>
+                                                </div>
+                                            </form>
+                                        </div>
                                     </div>
                                 </div>
                             </div>
@@ -1225,22 +1326,20 @@
         });
 
         // 启用、禁用验证码
-        $('#is_captcha').on({
-            'switchChange.bootstrapSwitch': function (event, state) {
-                var is_captcha = state ? 1 : 0;
-
-                $.post("{{url('admin/setConfig')}}", {
-                    _token: '{{csrf_token()}}',
-                    name: 'is_captcha',
-                    value: is_captcha
-                }, function (ret) {
-                    layer.msg(ret.message, {time: 1000}, function () {
-                        if (ret.status == 'fail') {
-                            window.location.reload();
-                        }
-                    });
+        $('#is_captcha').change(function () {
+            var is_captcha = $(this).val();
+            
+            $.post("{{url('admin/setConfig')}}", {
+                _token: '{{csrf_token()}}',
+                name: 'is_captcha',
+                value: is_captcha
+            }, function (ret) {
+                layer.msg(ret.message, {time: 1000}, function () {
+                    if (ret.status == 'fail') {
+                        window.location.reload();
+                    }
                 });
-            }
+            });
         });
 
         // 启用、禁用免费邀请码
@@ -2027,6 +2126,40 @@
             $(this).val($(this).val().replace(/(\s+)/g, ''));
         });
 
+        // 设置极验的Id
+        function setGeetestId() {
+            var geetest_id = $("#geetest_id").val();
+
+            $.post("{{url('admin/setConfig')}}", {
+                _token: '{{csrf_token()}}',
+                name: 'geetest_id',
+                value: geetest_id
+            }, function (ret) {
+                layer.msg(ret.message, {time: 1000}, function () {
+                    if (ret.status == 'fail') {
+                        window.location.reload();
+                    }
+                });
+            });
+        }
+
+        // 设置极验的Key
+        function setGeetestKey() {
+            var geetest_key = $("#geetest_key").val();
+
+            $.post("{{url('admin/setConfig')}}", {
+                _token: '{{csrf_token()}}',
+                name: 'geetest_key',
+                value: geetest_key
+            }, function (ret) {
+                layer.msg(ret.message, {time: 1000}, function () {
+                    if (ret.status == 'fail') {
+                        window.location.reload();
+                    }
+                });
+            });
+        }
+
         // 设置最小积分
         $("#min_rand_traffic").change(function () {
             var min_rand_traffic = $(this).val();

+ 18 - 7
resources/views/auth/login.blade.php

@@ -27,13 +27,24 @@
             <input class="form-control form-control-solid placeholder-no-fix" type="password" autocomplete="off" placeholder="{{trans('login.password')}}" name="password" value="{{Request::old('password')}}" required />
             <input type="hidden" name="_token" value="{{csrf_token()}}" />
         </div>
-        @if(\App\Components\Helpers::systemConfig()['is_captcha'])
-            <div class="form-group" style="margin-bottom:65px;">
-                <label class="control-label visible-ie8 visible-ie9">{{trans('login.captcha')}}</label>
-                <input class="form-control form-control-solid placeholder-no-fix" style="width:60%;float:left;" type="text" autocomplete="off" placeholder="{{trans('login.captcha')}}" name="captcha" value="" />
-                <img src="{{captcha_src()}}" onclick="this.src='/captcha/default?'+Math.random()" alt="{{trans('login.captcha')}}" style="float:right;" />
-            </div>
-        @endif
+        @switch(\App\Components\Helpers::systemConfig()['is_captcha'])
+            @case(1)
+                <!-- Default Captcha -->
+                <div class="form-group" style="margin-bottom:65px;">
+                    <label class="control-label visible-ie8 visible-ie9">{{trans('login.captcha')}}</label>
+                    <input class="form-control form-control-solid placeholder-no-fix" style="width:60%;float:left;" type="text" autocomplete="off" placeholder="{{trans('login.captcha')}}" name="captcha" value="" />
+                    <img src="{{captcha_src()}}" onclick="this.src='/captcha/default?'+Math.random()" alt="{{trans('login.captcha')}}" style="float:right;" />
+                </div>
+                @break
+            @case(2)
+                <!-- Geetest -->
+                <div class="form-group">
+                    {!! Geetest::render() !!}
+                </div>
+                @break
+            @default
+                @break
+        @endswitch
         <div class="form-actions">
             <div class="pull-left">
                 <label class="rememberme mt-checkbox mt-checkbox-outline">

+ 97 - 0
resources/views/vendor/geetest/geetest.blade.php

@@ -0,0 +1,97 @@
+<script src="https://cdn.bootcss.com/jquery/2.1.0/jquery.min.js"></script>
+<script src="https://static.geetest.com/static/tools/gt.js"></script>
+<div id="{{ $captchaid }}"></div>
+<p id="wait-{{ $captchaid }}" class="show">正在加载验证码...</p>
+@define use Illuminate\Support\Facades\Config
+<script>
+    var geetest = function(url) {
+        var handlerEmbed = function(captchaObj) {
+            $("#{{ $captchaid }}").closest('form').submit(function(e) {
+                // captchaObj.verify();
+                var validate = captchaObj.getValidate();
+                if (!validate) {
+                    Msg(false, '{{ Config::get('geetest.client_fail_alert')}}', 'error');
+                    e.preventDefault();
+                }
+            });
+            captchaObj.appendTo("#{{ $captchaid }}");
+            captchaObj.onReady(function() {
+                $("#wait-{{ $captchaid }}")[0].className = "hide";
+            })
+            captchaObj.onSuccess(function() {
+                // 进行服务器端二次验证
+                var result = captchaObj.getValidate();
+                
+                $.ajax({
+                    url: "{{url('geetestVerify')}}",
+                    type: 'post',
+                    dataType: 'json',
+                    data: {
+                        geetest_challenge: result.geetest_challenge,
+                        geetest_validate: result.geetest_validate,
+                        geetest_seccode: result.geetest_seccode,
+                        _token: '{{csrf_token()}}',
+                    },
+                    success: function(res) {
+                        Msg(true);
+                    },
+                    error: function(err) {
+                        Msg(false, err.responseJSON.errors.geetest_challenge + ',请重新验证', 'error');
+                        captchaObj.reset();
+                    }
+                })
+            })
+            if ('{{ $product }}' == 'popup') {
+                captchaObj.bindOn($('#{{ $captchaid }}').closest('form').find(':submit'));
+                captchaObj.appendTo("#{{ $captchaid }}");
+            }
+        };
+        
+        // 前端第一次验证
+        $.ajax({
+            url: url + "?t=" + (new Date()).getTime(),
+            type: "get",
+            dataType: "json",
+            success: function(data) {
+                initGeetest({
+                    gt: data.gt,
+                    challenge: data.challenge,
+                    product: "{{ $product?$product:Config::get('geetest.product', 'float') }}",
+                    offline: !data.success, // 表示用户后台检测极验服务器是否宕机
+                    new_captcha: data.new_captcha,  // 用于宕机时表示是新验证码的宕机
+                    lang: '{{ Config::get('geetest.lang', 'zh-cn') }}',
+                    http: '{{ Config::get('geetest.protocol', 'http') }}' + '://',
+                    width: '100%'
+                }, handlerEmbed);
+            }
+        });
+    };
+
+    function Msg(clear, msg, type) {
+        if ( !clear ) $('.login-form .alert').remove();
+        
+        var typeClass = 'alert-danger',
+            clear = clear ? clear : false,
+            $elem = $('.login-form');
+        type === 'error' ? typeClass = 'alert-danger' : typeClass = 'alert-success';
+
+        var tpl = '<div class="alert ' + typeClass + '">' +
+                '<button class="close" data-close="alert"></button>' +
+                '<span> ' + msg + ' </span></div>';
+        
+        if ( !clear ) {
+            $elem.prepend(tpl);
+        } else {
+            $('.login-form .alert').remove();
+        }
+    }
+
+    (function() {
+        geetest('{{ $url?$url:Config::get('geetest.url', 'geetest') }}');
+    })();
+</script>
+<style>
+    .hide {
+        display: none;
+    }
+</style>

+ 1 - 0
routes/web.php

@@ -16,6 +16,7 @@ Route::group(['middleware' => ['isForbidden', 'affiliate']], function () {
     Route::get('makePasswd', 'Controller@makePasswd'); // 生成密码
     Route::get('makeVmessId', 'Controller@makeVmessId'); // 生成VmessId
     Route::get('makeSecurityCode', 'Controller@makeSecurityCode'); // 生成网站安全码
+    Route::post('geetestVerify', 'CaptchaController@geetestPostValidate'); // Geetest 极验后端验证
 });
 
 Route::group(['middleware' => ['isForbidden', 'isLogin', 'isAdmin']], function () {

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików