Просмотр исходного кода

Weenier 168otc项目部署 0630

wesmiler 3 лет назад
Родитель
Сommit
5d75b46b77

+ 108 - 0
vendor/earnp/laravel-google-authenticator/README.md

@@ -0,0 +1,108 @@
+Google 身份验证器与两步验证功能配合,可在您登录 Google 帐户时为您平添一重安全保障。启用两步验证之后,当您登录帐户时,需要提供密码和此应用生成的验证码。配置完成后,无需网络连接或蜂窝连接即可获得验证码。
+
+# 为什么使用两步认证
+1. 相对于验证码,安全很多;几乎是不会存在破解的方法
+1. 验证码有时候无法识别,不方便操作
+1. 一机一码,不会存在账号盗用的问题
+1. 动态验证,每30秒生产一个验证码,安全更加保障
+
+# 开发前的准备  
+1. 安装Laravel  
+1. 安装二维码生成器`QrCode`,没有安装也可以,接下来会安装
+
+# 安装拓展
+1、运行如下代码安装拓展包:
+```
+composer require "earnp/laravel-google-authenticator:dev-master"
+# 安装二维码生成器
+composer require simplesoftwareio/simple-qrcode 1.3.*
+
+```
+3.等待下载安装完成,需要在`config/app.php`中注册服务提供者同时注册下相应门面:
+```php
+'providers' => [
+    //........
+    Earnp\GoogleAuthenticator\GoogleAuthenticatorServiceprovider::class,
+    SimpleSoftwareIO\QrCode\QrCodeServiceProvider::class,
+],
+
+'aliases' => [
+     //..........
+    'Google' => Earnp\GoogleAuthenticator\Facades\GoogleAuthenticator::class,
+    'QrCode' => SimpleSoftwareIO\QrCode\Facades\QrCode::class
+],
+```
+服务注入以后,如果要使用自定义的配置,还可以发布配置文件到config/views目录:
+```php
+php artisan vendor:publish
+```
+
+注意绑定视图位置为`resources/views/login/google/google.blade.php`,然后您可以在`config/google.php`中修改`账号名`和`绑定验证地址`。
+
+# 使用
+使用方法非常简单,主要为生成验证码和教研验证码
+### 1、生产验证码
+生产验证码使用`CreateSecret`即可,你需要将其内容生成二维码供手机APP扫描,具体内容在`google.blade.php`中已经配置成功
+```
+// 创建谷歌验证码
+$createSecret = Google::CreateSecret();
+// 您自定义的参数,随表单返回,用于绑定
+$parameter = [["name"=>"usename","value"=>"123"],["name"=>"users_id","value"=>encrypt("123")]];
+return view('login.google.google', ['createSecret' => $createSecret,"parameter" => $parameter]);
+```
+
+### 2、校验验证码
+校验验证码一般用于绑定,登录认证中,使用`CheckCode`方法即可,需要传入`secrect`和`onecode`即验证码即可进行校验,第一个为`secrect`;返回`true`或`false`
+
+```
+if(Google::CheckCode($google,$request->onecode)) {
+    // 绑定场景:绑定成功,向数据库插入google参数,跳转到登录界面让用户登录
+    // 登录认证场景:认证成功,执行认证操作
+    dd("认证成功");
+}
+else
+{
+    // 绑定场景:认证失败,返回重新绑定,刷新新的二维码
+    return back()->with('msg','请正确输入手机上google验证码 !')->withInput();
+    // 登录认证场景:认证失败,返回重新绑定,刷新新的二维码
+    return back()->with('msg','验证码错误,请输入正确的验证码 !')->withInput();
+}
+```
+
+这里有一个具体的实际事例:
+
+```
+use Google;
+
+
+if ($request->isMethod('post')) {
+    if (empty($request->onecode) && strlen($request->onecode) != 6) return back()->with('msg','请正确输入手机上google验证码 !')->withInput();
+    // google密钥,绑定的时候为生成的密钥;如果是绑定后登录,从数据库取以前绑定的密钥
+    $google = $request->google;
+    // 验证验证码和密钥是否相同
+    if(Google::CheckCode($google,$request->onecode)) {
+        // 绑定场景:绑定成功,向数据库插入google参数,跳转到登录界面让用户登录
+        // 登录认证场景:认证成功,执行认证操作
+        dd("认证成功");
+    }
+    else
+    {
+        // 绑定场景:认证失败,返回重新绑定,刷新新的二维码
+        return back()->with('msg','请正确输入手机上google验证码 !')->withInput();
+        // 登录认证场景:认证失败,返回重新绑定,刷新新的二维码
+        return back()->with('msg','验证码错误,请输入正确的验证码 !')->withInput();
+    }
+}
+else
+{
+    // 创建谷歌验证码
+    $createSecret = Google::CreateSecret();
+    // 您自定义的参数,随表单返回
+    $parameter = [["name"=>"usename","value"=>"123"]];
+    return view('login.google.google', ['createSecret' => $createSecret,"parameter" => $parameter]);
+}
+```
+
+# 使用与帮助
+
+拓展技术支持与问题反馈:[使用laravel-google-authenticator 拓展包为你的网站打造一个动态手机令牌](https://phpartisan.cn/news/49.html) 

+ 19 - 0
vendor/earnp/laravel-google-authenticator/composer.json

@@ -0,0 +1,19 @@
+{
+    "name": "earnp/laravel-google-authenticator",
+    "description": "Laravel 5 GoogleAuthenticator Package",
+    "authors": [
+        {
+            "name": "lusong",
+            "email": "714628712@qq.com",
+            "homepage": "https://phpartisan.cn"
+        }
+    ],
+    "license": "MIT",
+    "minimum-stability": "dev",
+    "require": {},
+    "autoload": {
+      "psr-4": {
+        "Earnp\\GoogleAuthenticator\\": "src/"
+      }
+    }
+}

+ 13 - 0
vendor/earnp/laravel-google-authenticator/src/Facades/GoogleAuthenticator.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace Earnp\GoogleAuthenticator\Facades;
+
+use Illuminate\Support\Facades\Facade;
+
+class GoogleAuthenticator extends Facade
+{
+    protected static function getFacadeAccessor()
+    {
+        return 'GoogleAuthenticator';
+    }
+}

+ 34 - 0
vendor/earnp/laravel-google-authenticator/src/GoogleAuthenticator.php

@@ -0,0 +1,34 @@
+<?php 
+namespace Earnp\GoogleAuthenticator;
+
+use App\Http\Controllers\Controller;
+use Illuminate\Support\Facades\Config;
+use Earnp\GoogleAuthenticator\Librarys\GoogleAuthenticator as GoogleSecretAuthenticator;
+
+class GoogleAuthenticator
+{
+    /**
+     * Show the application welcome screen to the user.
+     *
+     * @return Response
+     */
+
+    public static function CheckCode($secret,$oneCode)
+    {
+        $google = new GoogleSecretAuthenticator();
+        $checkResult = $google->verifyCode($secret,$oneCode, 2);//对传入的参数进行校验
+        if ($checkResult) return true;//校验成功
+        return false;//校验失败
+        
+    }
+
+    public static function CreateSecret()
+    {
+        $google = new GoogleSecretAuthenticator();
+        $secret = $google->createSecret();//创建一个Secret
+        $qrCodeUrl="otpauth://totp/".config("google.authenticatorname")."?secret=".$secret;//二维码中填充的内容
+        $googlesecret = array('secret' =>$secret ,'codeurl'=>$qrCodeUrl);
+        return $googlesecret;
+    }
+
+}

+ 47 - 0
vendor/earnp/laravel-google-authenticator/src/GoogleAuthenticatorServiceprovider.php

@@ -0,0 +1,47 @@
+<?php 
+namespace Earnp\GoogleAuthenticator;
+
+use Illuminate\Support\ServiceProvider;
+use Illuminate\Routing\Router;
+
+class GoogleAuthenticatorServiceprovider extends ServiceProvider
+{
+    /**
+     * Indicates if loading of the provider is deferred.
+     *
+     * @var bool
+     */
+    protected $defer = false;
+    public function boot()
+    {
+        // this for conig
+        $this->publishes([
+            __DIR__.'/config/google.php' => config_path('google.php'),
+        ]);
+
+        $this->publishes([
+            __DIR__.'/images/google' => public_path('images/google'),
+        ], 'public');
+
+        $this->loadViewsFrom(__DIR__.'/views', 'google');
+
+        $this->publishes([
+            __DIR__.'/views' => resource_path('views/login/google'),
+        ]);
+    }
+
+    /**
+     * Define the routes for the application.
+     *
+     * @param \Illuminate\Routing\Router $router
+     * @return void
+     */
+
+
+    public function register()
+    {
+        $this->app->bind('GoogleAuthenticator',function($app){
+            return new GoogleAuthenticator();
+        });
+    }
+}

+ 211 - 0
vendor/earnp/laravel-google-authenticator/src/Librarys/GoogleAuthenticator.php

@@ -0,0 +1,211 @@
+<?php
+
+/**
+ * PHP Class for handling Google Authenticator 2-factor authentication
+ *
+ * @author Michael Kliewe
+ * @copyright 2012 Michael Kliewe
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @link http://www.phpgangsta.de/
+ */
+
+namespace Earnp\GoogleAuthenticator\Librarys;
+
+class GoogleAuthenticator
+{
+    protected $_codeLength = 6;
+
+    /**
+     * Create new secret.
+     * 16 characters, randomly chosen from the allowed base32 characters.
+     *
+     * @param int $secretLength
+     * @return string
+     */
+    public function createSecret($secretLength = 16)
+    {
+        $validChars = $this->_getBase32LookupTable();
+        unset($validChars[32]);
+
+        $secret = '';
+        for ($i = 0; $i < $secretLength; $i++) {
+            $secret .= $validChars[array_rand($validChars)];
+        }
+        return $secret;
+    }
+
+    /**
+     * Calculate the code, with given secret and point in time
+     *
+     * @param string $secret
+     * @param int|null $timeSlice
+     * @return string
+     */
+    public function getCode($secret, $timeSlice = null)
+    {
+        if ($timeSlice === null) {
+			date_default_timezone_set('PRC');
+            $timeSlice = floor(time() / 30);
+        }
+
+        $secretkey = $this->_base32Decode($secret);
+
+        // Pack time into binary string
+        $time = chr(0).chr(0).chr(0).chr(0).pack('N*', $timeSlice);
+        // Hash it with users secret key
+        $hm = hash_hmac('SHA1', $time, $secretkey, true);
+        // Use last nipple of result as index/offset
+        $offset = ord(substr($hm, -1)) & 0x0F;
+        // grab 4 bytes of the result
+        $hashpart = substr($hm, $offset, 4);
+
+        // Unpak binary value
+        $value = unpack('N', $hashpart);
+        $value = $value[1];
+        // Only 32 bits
+        $value = $value & 0x7FFFFFFF;
+
+        $modulo = pow(10, $this->_codeLength);
+        return str_pad($value % $modulo, $this->_codeLength, '0', STR_PAD_LEFT);
+    }
+
+    /**
+     * Get QR-Code URL for image, from google charts
+     *
+     * @param string $name
+     * @param string $secret
+     * @param string $title
+     * @return string
+     */
+    public function getQRCodeGoogleUrl($name, $secret, $title = null) {
+        $urlencoded = urlencode('otpauth://totp/'.$name.'?secret='.$secret.'');
+	if(isset($title)) {
+                $urlencoded .= urlencode('&issuer='.urlencode($title));
+        }
+        return $urlencoded;
+    }
+
+    /**
+     * Check if the code is correct. This will accept codes starting from $discrepancy*30sec ago to $discrepancy*30sec from now
+     *
+     * @param string $secret
+     * @param string $code
+     * @param int $discrepancy This is the allowed time drift in 30 second units (8 means 4 minutes before or after)
+     * @param int|null $currentTimeSlice time slice if we want use other that time()
+     * @return bool
+     */
+    public function verifyCode($secret, $code, $discrepancy = 1, $currentTimeSlice = null)
+    {
+        if ($currentTimeSlice === null) {
+            $currentTimeSlice = floor(time() / 30);
+        }
+
+        for ($i = -$discrepancy; $i <= $discrepancy; $i++) {
+            $calculatedCode = $this->getCode($secret, $currentTimeSlice + $i);
+            if ($calculatedCode == $code ) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Set the code length, should be >=6
+     *
+     * @param int $length
+     * @return PHPGangsta_GoogleAuthenticator
+     */
+    public function setCodeLength($length)
+    {
+        $this->_codeLength = $length;
+        return $this;
+    }
+
+    /**
+     * Helper class to decode base32
+     *
+     * @param $secret
+     * @return bool|string
+     */
+    protected function _base32Decode($secret)
+    {
+        if (empty($secret)) return '';
+
+        $base32chars = $this->_getBase32LookupTable();
+        $base32charsFlipped = array_flip($base32chars);
+
+        $paddingCharCount = substr_count($secret, $base32chars[32]);
+        $allowedValues = array(6, 4, 3, 1, 0);
+        if (!in_array($paddingCharCount, $allowedValues)) return false;
+        for ($i = 0; $i < 4; $i++){
+            if ($paddingCharCount == $allowedValues[$i] &&
+                substr($secret, -($allowedValues[$i])) != str_repeat($base32chars[32], $allowedValues[$i])) return false;
+        }
+        $secret = str_replace('=','', $secret);
+        $secret = str_split($secret);
+        $binaryString = "";
+        for ($i = 0; $i < count($secret); $i = $i+8) {
+            $x = "";
+            if (!in_array($secret[$i], $base32chars)) return false;
+            for ($j = 0; $j < 8; $j++) {
+                $x .= str_pad(base_convert(@$base32charsFlipped[@$secret[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
+            }
+            $eightBits = str_split($x, 8);
+            for ($z = 0; $z < count($eightBits); $z++) {
+                $binaryString .= ( ($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48 ) ? $y:"";
+            }
+        }
+        return $binaryString;
+    }
+
+    /**
+     * Helper class to encode base32
+     *
+     * @param string $secret
+     * @param bool $padding
+     * @return string
+     */
+    protected function _base32Encode($secret, $padding = true)
+    {
+        if (empty($secret)) return '';
+
+        $base32chars = $this->_getBase32LookupTable();
+
+        $secret = str_split($secret);
+        $binaryString = "";
+        for ($i = 0; $i < count($secret); $i++) {
+            $binaryString .= str_pad(base_convert(ord($secret[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
+        }
+        $fiveBitBinaryArray = str_split($binaryString, 5);
+        $base32 = "";
+        $i = 0;
+        while ($i < count($fiveBitBinaryArray)) {
+            $base32 .= $base32chars[base_convert(str_pad($fiveBitBinaryArray[$i], 5, '0'), 2, 10)];
+            $i++;
+        }
+        if ($padding && ($x = strlen($binaryString) % 40) != 0) {
+            if ($x == 8) $base32 .= str_repeat($base32chars[32], 6);
+            elseif ($x == 16) $base32 .= str_repeat($base32chars[32], 4);
+            elseif ($x == 24) $base32 .= str_repeat($base32chars[32], 3);
+            elseif ($x == 32) $base32 .= $base32chars[32];
+        }
+        return $base32;
+    }
+
+    /**
+     * Get array with all 32 characters for decoding from/encoding to base32
+     *
+     * @return array
+     */
+    protected function _getBase32LookupTable()
+    {
+        return array(
+            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', //  7
+            'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
+            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
+            'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
+            '='  // padding char
+        );
+    }
+}

+ 6 - 0
vendor/earnp/laravel-google-authenticator/src/config/google.php

@@ -0,0 +1,6 @@
+<?php
+    return [
+    	// 中文需要UrlEncode转为utf8编码
+    	"authenticatorname" => "Laravel%e5%ad%a6%e4%b9%a0%e7%bd%91",
+		"authenticatorurl" => "",
+    ];

BIN
vendor/earnp/laravel-google-authenticator/src/images/google/android.png


BIN
vendor/earnp/laravel-google-authenticator/src/images/google/authenticator.jpg


BIN
vendor/earnp/laravel-google-authenticator/src/images/google/bindcard.jpg


BIN
vendor/earnp/laravel-google-authenticator/src/images/google/ios.png


+ 194 - 0
vendor/earnp/laravel-google-authenticator/src/views/google.blade.php

@@ -0,0 +1,194 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<meta name="author" content="phpartisan.cn"/>
+	<title>绑定Google验证码</title>
+	<script type="text/javascript">  
+	    function startTime()  
+	    {  
+	        //获取当前系统日期  
+			var myDate = new Date();
+	        var y=myDate.getFullYear(); //获取当前年份(2位)
+	        var m=myDate.getMonth()+1; //获取当前月份(0-11,0代表1月)
+	        var d=myDate.getDate(); //获取当前日(1-31)
+	        var h=myDate.getHours(); //获取当前小时数(0-23)
+	        var mi=myDate.getMinutes(); //获取当前分钟数(0-59)
+	        var s=myDate.getSeconds(); //获取当前秒数(0-59)
+	        var hmiao=myDate.getMilliseconds(); //获取当前毫秒数(0-999)
+	        //s设置层txt的内容  
+	        document.getElementById('txt').innerHTML=y+"-"+m+"-"+d+" "+h+":"+mi+":"+s;  
+	        //过500毫秒再调用一次  
+	        t=setTimeout('startTime()',500)  
+	        //小于10,加0  
+	        function checkTime(i)  
+	        {  
+	            if(i<10)  
+	               {i="0"+i}  
+	               return i  
+	        }  
+	    }
+	</script>  
+	<style type="text/css">
+		body{
+			background-color:#2E363F;
+			margin:0px;
+			padding:0px;
+		}
+		ul,li{
+			list-style:none;
+			padding:0px;
+			margin:0px;
+		}
+		.container{
+			width:98%;
+			max-width:1000px;
+			min-width:600px;
+			background-color:#FFF;
+			height:1250px;
+			padding: 20px 20px 100px 20px;
+			margin: 30px auto;
+			line-height:25px;
+			font-family:微软雅黑;
+			font-size:15px;
+			color: #666666;
+		}
+		.container span{
+			font-weight:bold;
+			color: #666666;
+			font-size:15px;
+			line-height:35px;
+		}
+		.container h3{
+			font-size:24px;
+			color: #333333;
+		}
+		.container h4{
+			font-size:18px;
+			color: #333333;
+		}
+		.container h5{
+			font-size:15px;
+			color: #333333;
+		}			
+		.discription{
+			width:100%;
+			height:auto;
+			border-bottom:thin dashed #CCC;
+			padding-bottom: 20px;
+			float: left;
+		}
+		.appdownloadcode{
+			width:100%;
+			height:230px;
+			padding-top:20px;
+		}	
+		.appdownloadcode li{
+			width:50%;
+			float:left;
+			text-align:center;
+		}
+		.appdownloadcode img{
+			width:200px;
+			height:200px;
+			margin-left:auto;
+			margin-right:auto;
+		}		
+		.container-form{
+			width:100%;
+			height:230px;
+			padding-top:20px;
+			text-align:center;
+			margin-top: 30px;
+			float: left;
+		}
+		.container-form img{
+			width:250px;
+			height:250px;
+			margin: 0px auto 10px auto;
+			padding:5px;
+			border:thin solid #CCC;
+			border-radius:10px;
+		}	
+		.verificationcode{
+			width:300px;
+			height:35px;
+			outline:none;
+			border:thin solid #CCC;
+			font-family:微软雅黑;
+			font-size:14px;
+			padding-left:20px;
+			margin-top:20px;
+		}	
+		.submit-button{
+			width:150px;
+			height:35px;
+			border-radius: 2px;
+			outline:none;
+			background-color: #0C6;
+			color:#FFF;
+			font-family:微软雅黑;
+			border:none;
+			font-size:15px;
+			margin-top:20px;
+		}	
+		a{
+			color:#09C;
+		}
+		.notice{
+			width: 100%;
+			float: left;
+			color: #FF6666;
+			margin-top: 20px;
+		}				
+	</style>
+</head>
+
+<body onload="startTime()">
+	<div class="container">
+		<div class="discription">
+		    <h3>绑定谷歌验证器</h3>
+		    <h4>使用说明:</h4>
+	    	<p>如果遇到问题,请参考:<a href="https://phpartisan.cn/specials/5" target="_blank">Google Authenticator帮助文档</a></p>
+	    	<h5>步骤一:</h5>
+	    	<p>手机下载安装Google Authenticator。</p>
+	    	<div class="appdownloadcode">
+				<ul>
+					<li>
+						<img src="/images/google/ios.png" width="280" height="280" /><br />Ios扫描下载
+					</li>
+					<li>
+						<img src="/images/google/android.png" width="280" height="280" /><br />安卓扫描下载
+					</li>
+				</ul>
+			</div>
+			<h5>步骤二:</h5>
+			<p>软件安装完成后,选择开始设置-扫描条形码,来扫描本页面的二维码,扫描成功后,您手机里的谷歌验证器会生成一个与您账户对应的六位动态密码,每30秒变化一次。</p>
+			<h5>步骤三:</h5>
+			<p>之后您每次登陆时都需要输入谷歌验证码,无论手机是否连接网络都可以使用。在允许时间内输入有效数字,保证了账户安全。
+			</p>
+		</div>
+
+		<div class="container-form">
+			<p>本页面刷新后二维码会重置,请重新扫描</p>
+			{!! QrCode::encoding('UTF-8')->size(200)->margin(1)->generate($createSecret["codeurl"]); !!}
+			<br />服务器当前时间为:&nbsp;&nbsp;<font id="txt"></font>
+			<br />如果图片无法显示或者无法扫描,请在手机登录器中手动输入:
+			<font color="#FF6666">{{ $createSecret["secret"] }}</font>
+			<form action="{{ empty(Config::get('google.authenticatorurl')) ? URL::current() : Config::get('google.authenticatorurl') }}" method="POST">
+				{!! csrf_field() !!}
+				<input name="onecode" type="text" class="verificationcode" placeholder="请输入扫描后手机显示的6位验证码" value="{{ old('onecode') }}" />
+				@foreach($parameter as $parame)
+				<input type="hidden" name="{{ $parame['name'] }}" value="{{ $parame['value'] }}" />
+				@endforeach
+				<input type="hidden" name="google" value="{{ $createSecret['secret'] }}" />
+				<br />
+				<button class="submit-button">立即绑定</button>
+				@if(Session::has('msg'))
+				   <div class="notice">{{ Session::get('msg') }}</div>
+				@endif
+			</form>
+		</div>
+	</div>
+</body>
+</html>