接觸Laravel是2018年,當年期望借此能從一個做小板凳的升級為做傢具的,搞不好成為一專業木匠.可一轉眼都2020年了,我依然是在門外轉悠,偶爾做做小板凳,想想也是頗為汗顏.
這就是我等的通病,沒恒心缺毅力,所以人到中年,淪為一個數字.
然而,只要今天又想到學,那就記錄下來備用.萬一后面用到呢!
前言
Laravel 支持多種認證方式,對企業環境來說AD LDAP認證的方式就很實用,但更好的方式是使用Windows集成認證,省掉輸入賬號密碼這一步.
單純的配置Laravel使用Windows集成認證并不複雜,我的目標是加入Windows 域的電腦通過Windows集成認證,未加入域的電腦通過頁面認證.
看起來很簡單的一個任務居然斷斷續續的花了三天才算成功.
正文
1. 讓Laravel 可以通過Windows 集成認證
1.1 Linux 啟用Windows集成認證(略)
1.2 Laravel 獲取通過Windows集成認證后的身份信息
1.2.1 新建一個用于Windows集成認證的中間件WinSSO
[root@ksyoweb02 ldap]# php artisan make:middleware WinSSO
Middleware created successfully.
1.2.2 編輯WinSSO[app\Http\Middleware\WinSSO.php],使其可驗證User.
<?php
namespace App\Http\Middleware;
use Closure;
use App\User;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\Factory as Auth;
class WinSSO
{
protected $auth;
public function __construct(Auth $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->server('REMOTE_USER') ){//如果通過認證,會有REMOTE_USER
$ssoUserArr=explode("@",$request->server('REMOTE_USER'));//REMOTE_USER中包含域名,分割一下
if ($user = User::where('username', $ssoUserArr[0])->first())//在USER對象中查詢是否匹配
{
$this->auth->login($user);//授權
}
}
else
{
return redirect()->guest('login');//否則跳回登錄窗口
}
return $next($request);//授權后的信息返回
}
}
1.2.3 在kernel.php[app\Http\Kernel.php]中註冊中間件,注意加入到$routeMiddleware中
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'op' => \App\Http\Middleware\AuthOp::class,
'sso' => \App\Http\Middleware\WinSSO::class,
];
1.2.4 在需要的Controller中使用中間件,比如HomeController
public function __construct()
{//不同情境下使用不同中間件來進行驗證
if(array_key_exists('REMOTE_USER',$_SERVER)){
$this->middleware('sso');
}else{
$this->middleware('auth');
}
}
2. 讓未加入域的電腦不彈出http base auth,直接轉到頁面認證
在這部份我花費了比較長的時間,主要是因為腦子不夠清晰走了彎路.重點如下:
- laravel 入口文件為index.php,可以看作每次訪問都只是訪問index.php這一個文件
- 401 重定向有限制,而且行為比較詭異
我最終的方案是使用vhost+軟鏈接,讓同一工程有兩個不同入口,分別採用不同的權限以達到目的.
2.1 為工程目錄軟鏈接一個虛擬目錄
[root@ksyoweb02 html]# ln -s website website8000
2.2 用兩個vhost來分配不同的訪問權限方式
[root@ksyoweb02 html]# vim /etc/httpd/vhost.d/web.conf
#80端口需要SSO認證
<VirtualHost *:80>
ServerName ksyoweb02.youngoptics.com
ServerAlias ksyoweb02.youngoptics.com
DocumentRoot /var/www/html/website/public
</VirtualHost>
<Directory "/var/www/html/website/public">
Options +Includes -Indexes
AllowOverride All
AuthType Kerberos
AuthName "HHH"
KrbMethodNegotiate On
KrbMethodK5Passwd Off #自動認證失敗時不彈出窗口要求賬號密碼
KrbAuthRealms YOUNGOPTICS.COM
Krb5KeyTab /etc/httpd/ksyoweb02.keytab
KrbServiceName HTTP
require valid-user
ErrorDocument 401 /redirect.html #401 時訪問redirect.html 這個文件,這里不能直接外部url
<Files "redirect.html">
require all granted #指定訪問此文件時不需要驗證
</files>
</Directory>
[root@ksyoweb02 html]# vim /etc/httpd/vhost.d/web8000.conf
Listen 8000 #8000端口不需要SSO認證
<VirtualHost *:8000>
ServerName ksyoweb02
ServerAlias ksyoweb02
DocumentRoot /var/www/html/website8000/public
</VirtualHost>
<Directory "/var/www/html/website8000/public">
Options +Includes -Indexes
AllowOverride All
Require all granted
</Directory>
2.3 編輯redirect.html文件,以達到跳轉目的.
<html>
<head>
<title>Redirect To Login Form</title>
<meta charset="utf-8">
<meta http-equiv = "refresh" content = "2; url = http://ksyoweb02.youngoptics.com:8000" />
</head>
<body>
<p>自動認證失敗,正在轉入登錄界面!</p>
</body>
</html>
此處我原想用php來做跳轉,邪門的是如果用php 跳轉,那不管401不401都會跳走,但如果是php輸出內容又可以,真是日了狗了.
<?PHP
$url = "http://ksyoweb02.youngoptics.com:8000";
Header("HTTP/1.1 303 See Other");
Header("Location: $url");
exit;
?>
結束