ホームページ >バックエンド開発 >PHPチュートリアル >PHP の第 7 弾 - ロールベースのアクセス制御 RBAC_PHP チュートリアルに関する簡単な説明

PHP の第 7 弾 - ロールベースのアクセス制御 RBAC_PHP チュートリアルに関する簡単な説明

WBOY
WBOYオリジナル
2016-07-13 17:50:42927ブラウズ

上記の記事 http://www.BkJia.com/kf/201205/129972.html では、ループを使用して乗算表を出力する方法を説明しています。そのロジックは比較的単純です。プログラムを表示して分析し、コードのメソッドやアイデアについてコメントや提案があれば、コメントして批判してください。

はい、これ以上の話は不要です。この記事では「ロールベースのアクセス制御」について紹介します。

権限といえば、ユーザーの権限をどのように柔軟に制御できるかについて誰もが頭を悩ませています。

一部の学生は、フィールドをユーザー テーブルに追加するか、対応する権限フィールドをロール テーブルに追加します。

これには問題があり、権限が追加されるたびにフィールドがデータベースに追加されるため、プロジェクトの反復的な開発には役立ちません。

次に、非常に柔軟な設計パターン RBAC、つまりロールベースのアクセス制御が必要になります。

このデザインのアイデアについてお話しましょう:

まず第一に、ユーザーが現在操作されているコントローラーまたはコントローラー メソッドにアクセスする権限を持っているかどうかを判断する必要があります。

複数のユーザーが同時に同じ権限を持っている場合は、これらのユーザーに同じユーザー ロールを割り当てる必要があり、そのロールを通じて操作へのアクセスを制御するだけで済みます。

次に、テーブル構造を次のように設計する必要があります。これは非常に重要です。

最初のデータテーブル (ユーザーテーブル):


フィールド名2番目のデータテーブル(文字テーブル):
フィールドの説明 ID
ユーザーID (主キー自動インクリメント) ユーザー名
ユーザー名 パスワード
ユーザーパスワード


フィールド名3番目のデータテーブル(ノードテーブル):
フィールドの説明 ID
ユーザーロールID (主キー自動インクリメント) 名前
ユーザーロール名


フィールド名関連テーブルの設計には第 3 正規形を使用します。これの利点は、データの冗長性を回避し、1 対多および多対 1 の関係を明確に記録して整理できることです。 4番目のデータテーブル(ノード対応ロールテーブル):
フィールドの説明 ID
操作ノードID(主キー自動インクリメント) 名前
操作ノードの名前 zh_name
ノードの中国語説明


フィールド名

フィールドの説明ユーザーロールID (外部キー、関連付けられたロールテーブルの主キーID)操作ノードID(外部キー、関連ノードテーブルの主キーID)
role_id
note_id
5番目のデータテーブル(ユーザー対応ロールテーブル):


フィールド名

フィールドの説明ユーザーロールID (外部キー、関連付けられたロールテーブルの主キーID)ユーザーID (外部キー、関連するユーザーテーブルの主キーID)
role_id
ユーザーID

これら 5 つのテーブルを通じてアクセス制御を実行できます。具体的な操作手順は次のとおりです。

ユーザーはユーザー名とパスワードを入力してログインします。

ユーザーテーブルから判断して、入力されたユーザー名とパスワードが不正な場合は、戻って再度ログインしてください
正当な場合は、ユーザー テーブル内のユーザーの ID 番号を返します。
このユーザー ID 番号を通じて、ユーザーとロール間の関連付けテーブル内のユーザーのロール ID 番号をクエリします。
ロール ID 番号を取得し、この ID 番号を使用してロールとノード間の関連付けテーブルをクエリし、このロールが所有するノード アクセス権を確認します。
ユーザーが特定のモジュールにアクセスすると、これらすべての権限ノードが SESSION に保存されます。
例: http://www.lampbroher.net/index.php/stu/index

セッション内の権限を使用して、$_GET['m'] と $_GET['a'] を比較します。

$_GET['m'] または $_GET['a'] が SESSION に存在しない場合は、ユーザーにこの権限がないことを意味します。そのまま処理してください。

参照コード:

RBACクラスファイル:

/*+----------------------------------------------- ----------------------------------------------------+
| RBAC 権限制御クラス

クラス Rbac{
private $node_tablename; //プライベート属性ノードテーブル名を定義します
private $group_auth_tablename; //プライベート属性グループ権限テーブル名を定義します
private $group_tablename; //プライベート属性のユーザーグループテーブル名を定義します
private $group_user_tablename; //プライベート属性のユーザー所属グループテーブル名を定義します
private $user_tablename; //プライベート属性のユーザーテーブル名を定義します
/*
施工方法
@param1 文字列ノードテーブル名
@param2 string ユーザー権限テーブル名
@param3 文字列ユーザーグループテーブル名
@param4 string ユーザー所属グループテーブル名
@param5 文字列ユーザーテーブル名
*/
public function __construct($node_tablename='node',$group_auth_tablename='group_auth',$group_tablename='group',$group_user_tablename='group_member',$user_tablename='member'){
$this->node_tablename = $node_tablename //ノードテーブル名を取得します
; $this->group_auth_tablename = $group_auth_tablename //ユーザー権限テーブル名を取得します
; $this->group_tablename = $group_tablename //ユーザーグループテーブル名を取得します
$this->group_user_tablename = $group_user_tablename //ユーザーのグループテーブルの名前を取得します
; $this->user_tablename = $user_tablename //ユーザーテーブル名を取得します
}
/*
ノードメソッドの設定
@param1 文字列ノード名
@param2 文字列ノードの親 ID
@param2 文字列ノードの中国語の説明
@return int ノードレコードの挿入に成功した後のID
*/
パブリック関数 set_node($name,$pid,$zh_name=''){
if(!empty($name) && !empty($pid)){
$node = D($this->node_tablename)->insert(array("name"=>$name,"pid"=>$pid,"zh_name"=>$zh_name));
}
$node を返します;
}
/*
権限の設定方法
@param1 int グループ ID
@param2 int ノード ID
@return int ID パーミッションレコードが正常に挿入された後
*/
パブリック関数 set_auth($gid,$nid){
if(!empty($gid) && !empty($nid)){
$auth = D($this->group_auth_tablename)->insert(array("gid"=>$gid,"nid"=>$nid));
}
$auth を返します;
}
/*
ノードメソッドの取得
@param1 int ノード ID
@return array ノードテーブルの関連情報を取得します
*/
パブリック関数 get_node($id){
if(!empty($id)){
$data = D($this->node_tablename)->field("id,name,pid")->where(array('id'=>$id))->find();
$data を返します;
}その他{
false を返します;
}
}
/*
グループ権限を取得する方法
@param1 int ユーザーグループ ID
@return array グループ権限テーブルの関連情報を取得します
*/
パブリック関数 get_auth($gid){
if(!empty($gid)){
$data = D($this->group_auth_tablename)->field("nid")->where(array('gid'=>$gid))->select();
$data を返します;
}その他{
false を返します;
}
}
/*
ユーザーグループの取得方法
@param1 int ユーザー ID
@return array ユーザーに対応するユーザーグループIDを取得します
*/
パブリック関数 get_group($uid){
if(!empty($uid)){
$data = D($this->group_user_tablename)->field("gid")->where(array('uid'=>$uid))->select();
$data を返します;
}その他{
false を返します;
}
}
/*
ノードの子ノードメソッドを取得します
@param1 int ノード ID
@return array このノードに対応するすべての子ノードを取得します
*/
パブリック関数 get_cnode($nid){
if(!empty($nid)){
$cnode = D($this->node_tablename)->field("name")->where(array('pid'=>$nid))->select();
$cnode を返します;
}その他{
false を返します;
}
}
/*
許可の取得方法
@param1 int ユーザー ID
@return array 権限リストを取得します
*/
パブリック関数 get_access($uid){
if(!empty($uid)){
//メソッドを呼び出してグループ情報を取得します
$group = $this->get_group($uid);
//グループ情報をトラバースします
foreach($group as $v){
//グループIDをメソッドに渡して権限を取得します
$auth = $this->get_auth($v['gid']) // グループの権限を取得します
; }
//グループの権限配列を走査します
foreach($auth as $val){
//ノード情報を取得するメソッドにノードIDを渡します
$node[] = $this->get_node($val['nid']) //ノード関連の情報を取得します
}
// ノード配列を走査してアセンブルします
foreach($node as $nval){
if($nval['pid']==0){
$fnode[] = $nval //コントローラーを fnode 配列にプッシュします
; //$cnode = $this->get_cnode($nval['id']);
}その他{
$cnode[] = $nval //コントローラーメソッドを cnode 配列にプッシュします
; }
}
// コントローラー配列とコントローラー配列を 1 つの配列にアセンブルします
foreach($fnode as $fval){
foreach($cnode as $cval){
if($cval['pid'] == $fval['id']){
$access[$fval['name']][] = $cval['name'];
}
}
}
// 権限リストの配列を返します
$access を返します;
}その他{
false を返します;
}
}
/*
権限を確認する方法
@param1 int ユーザー ID
@return boolean 許可が禁止されているかどうか
*/
パブリック関数チェック($uid){
if(!empty($uid)){
// 権限を $_SESSION['Access_List'] に保存します
$_SESSION['Access_List'] = $this->get_access($uid);
if(!empty($_GET['m'])){
//このコントローラーが許可されているかどうかを判断します
if(array_key_exists($_GET['m'],$_SESSION['Access_List'])){
//このコントローラーのメソッドが許可されているかどうかを判断します
if(in_array($_GET['a'],$_SESSION['Access_List'][$_GET['m']])){
// 許可されている場合は true を返します
true を返します;
}その他{
// それ以外の場合は false を返します
false を返します;
}
}その他{
false を返します;
}
}その他{
false を返します;
}
}その他{
//$_SESSION['user_'.$uid]['Access_List'] = 0;
false を返します;
}
}
パブリック関数 show_node(){
$path = APP_PATH.'/controls/';
$handle = opendir($path);
while(false!==($data = readdir($handle))){
if(is_file($path.$data) && $data!='common.class.php' && $data!='pub.class.php'){
$controller = str_replace(".class.php",'',$data);
$res = fopen($path.$data,'r');
$str = fread($res,filesize($path.$data));
$pattern = '/function(.*)()/iU';
preg_match_all($pattern, $str, $matches);
foreach($matches[1] as $v){
$v = トリム($v);
$arr[$controller][] = $v;
}
}
}
Closedir($handle);
$arr を返します;
}
}
初期化クラス:
/*+----------------------------------------------- ----------------------------------------------------+
| コントローラーを初期化します

クラス Common extends アクション {
/*
初期化方法
*/
パブリック関数 init(){
//SESSION が空の場合はジャンプ
if(empty($_SESSION['user_login'])){
$this->redirect("pub/index");
}
$a = 新しい rbac();
if(!$a->check($_SESSION['user_info']['id'])){
echo "<script>alert('この権限がありません!')</script>";
exit("