This article mainly introduces the ThinkPHP permission authentication Auth instance. if you need it, you can refer to the following example code to thoroughly analyze the implementation principles and methods of ThinkPHP permission authentication Auth. the specific steps are as follows:
Some SQL code of mysql database:
-- Optimize Table structure for think_auth_group -- -------------------------- drop table if exists 'think _ auth_group '; create table 'think _ auth_group' ('id' mediumint (8) unsigned not null AUTO_INCREMENT, 'title' char (100) not null default '', 'status' tinyint (1) not null default '1', 'rules' char (80) not null default '', primary key ('id') ENGINE = MyISAM AUTO_INCREMENT = 2 default charset = utf8 COMMENT = 'User group table '; -- ---------------------------- Records of think_auth_group -- -------------------------- insert into 'think _ auth_group 'VALUES ('1', 'administrative Group', '1', '1, 2 '); -- optimize Table structure for think_auth_group_access -- -------------------------- drop table if exists 'think _ auth_group_access '; create table 'think _ auth_group_access' ('uid' mediumint (8) unsigned not null comment 'user ID', 'group _ id' mediumint (8) unsigned not null comment 'user group ID', unique key 'uid _ group_id '('uid ', 'group _ id'), KEY 'uid' ('uid'), KEY 'group _ id' ('group _ id ')) ENGINE = MyISAM default charset = utf8 COMMENT = 'User group details'; -- returns Records of think_auth_group_access -- values insert into 'think _ auth_group_access 'values ('1', '1 '); insert into 'think _ auth_group_access 'VALUES ('1', '2'); -- optimize Table structure for think_auth_rule -- ------------------------ drop table if exists 'think _ auth_rule '; create table 'think _ auth_rule' ('id' mediumint (8) unsigned not null AUTO_INCREMENT, 'name' char (80) not null default ''comment' rule unique identifi ', 'title' char (20) not null default ''comment' rule Chinese name', 'status' tinyint (1) not null default '1' comment' status: 1 normal, if it is 0 disabled, 'type' char (80) not null, 'condition' char (100) not null default ''comment' rule expression. if it is NULL, it indicates that the rule exists, if this parameter is not set to Null, it indicates that ', primary key ('id'), and unique key 'name' ('name') are verified by condition ')) ENGINE = MyISAM AUTO_INCREMENT = 5 default charset = utf8 COMMENT = 'rule table'; -- COMMENT Records of think_auth_rule -- comment insert into 'think _ auth_rule' VALUES ('1 ', 'home/Index', 'list', '1', 'home', ''); insert into 'think _ auth_rule' VALUES ('2 ', 'home/add', 'Add', '1', 'home', ''); insert into 'think _ auth_rule' VALUES ('3 ', 'home/edit', 'edit', '1', 'home', ''); insert into 'think _ auth_rule' VALUES ('4 ', 'home/delete', 'delete', '1', 'home', ''); drop table if exists 'think _ user '; create table 'think _ user' ('id' int (11) not null, 'username' varchar (30) default null, 'password' varchar (32) default null, 'age' tinyint (2) default null, primary key ('id') ENGINE = InnoDB default charset = utf8; -- ---------------------------- Records of think_user -- ---------------------------- insert into 'think _ user' VALUES ('1', 'admin', 'region', '25 ');
Configuration file Application \ Common \ Conf \ config. php section:
<? Phpreturn array (// 'config map '=> 'configuration value' 'DB _ DSN' => '', // The database connection DSN is used in the PDO mode 'DB _ type' => 'mysql', // The database TYPE 'DB _ host' => 'localhost ', // The server address 'DB _ name' => 'thinkphp', // The database NAME 'DB _ user' => 'root ', // username 'DB _ pwd' => 'root', // password 'DB _ port' => 3306, // port 'DB _ prefix' => 'think _ ', // database table PREFIX 'auth _ config' => array ('auth _ on' => true, // authentication switch 'auth _ type' => 1, // authentication method. the value 1 indicates time-based authentication, and the value 2 indicates logon authentication. 'Auth _ group' => 'think _ auth_group ', // User GROUP data table name 'auth _ GROUP_ACCESS' => 'think _ auth_group_access ', // User group list 'auth _ rule' => 'think _ auth_rule ', // permission rule table 'auth _ user' => 'think _ user' // USER information table ));
Application \ Home \ Controller \ IndexController. class. php code of the Home Controller of the project:
<? Phpnamespace Home \ Controller; use Think \ Controller; class IndexController extends Controller {public function index () {$ Auth = new \ Think \ Auth (); // list of rules to be verified, supports comma-separated permission rules or index arrays $ name = MODULE_NAME. '/'. ACTION_NAME; // Current User ID $ uid = '1'; // Category $ type = MODULE_NAME; // check mode $ mode = 'URL '; // 'or' indicates that any rule is verified. // 'and' indicates that all rules must be met before verification $ relation = 'and '; if ($ Auth-> check ($ name, $ uid, $ type, $ mode, $ relation) {die ('authentication: successfully ');} else {die ('authentication: failed ');}}}
The above code is the most basic verification code example.
The following is the source code reading:
1. permission inspection class initialization configuration information:
$Auth = new \Think\Auth();
When an object is created, the program merges the configuration information.
The program merges the AUTH_CONFIG array in Application \ Common \ Conf \ config. php.
Public function _ construct () {$ prefix = C ('Db _ prefix'); $ this-> _ config ['auth _ group'] = $ PREFIX. $ this-> _ config ['auth _ group']; $ this-> _ config ['auth _ rule'] = $ prefix. $ this-> _ config ['auth _ rule']; $ this-> _ config ['auth _ user'] = $ prefix. $ this-> _ config ['auth _ user']; $ this-> _ config ['auth _ GROUP_ACCESS '] = $ prefix. $ this-> _ config ['auth _ GROUP_ACCESS ']; if (C ('auth _ config') {// you can set the configuration item AUTH_CONFIG. Items are arrays. $ This-> _ config = array_merge ($ this-> _ config, C ('auth _ config '));}}
2. Check permissions:
check($name, $uid, $type = 1, $mode = 'url', $relation = 'or')
Let's take a general analysis of this method.
First, determine whether to disable permission verification. if the configuration information is AUTH_ON => false, no permission verification will be performed. Otherwise, the permission verification will continue.
if (!$this->_config['AUTH_ON']) { return true;}
After obtaining the permission list, we will introduce it in detail:
$authList = $this->getAuthList($uid, $type);
The list of rules to be verified this time is converted to an array:
if (is_string($name)) { $name = strtolower($name); if (strpos($name, ',') !== false) { $name = explode(',', $name); } else { $name = array($name); }}
Therefore, the $ name parameter is case-insensitive and will eventually be converted to lowercase letters.
When the url mode is enabled, convert all to lowercase:
if ($mode == 'url') { $REQUEST = unserialize(strtolower(serialize($_REQUEST)));}
One of the core code segments of permission verification, that is, loop through all the user permissions to determine whether the current permissions to be verified are in the user authorization list:
Foreach ($ authList as $ auth) {$ query = preg_replace ('/^. + \? /U', '', $ auth); // Obtain the url parameter if ($ mode = 'URL' & $ query! = $ Auth) {parse_str ($ query, $ param); // Obtain the url parameter in the array format $ intersect = array_intersect_assoc ($ REQUEST, $ param ); $ auth = preg_replace ('/\?. * $/U', '', $ auth); // Obtain the Accessed url file if (in_array ($ auth, $ name) & $ intersect = $ param) {// if the node matches and the url parameter meets $ list [] = $ auth;} else if (in_array ($ auth, $ name )) {$ list [] = $ auth ;}}
In_array ($ auth, $ name): if one of the permissions in the permission list is equal to the permissions to be verified, add them to the $ list.
Note:
$ List = array (); // Save the rule name if ($ relation = 'or' and! Empty ($ list) {return true;} $ diff = array_diff ($ name, $ list); if ($ relation = 'and' and empty ($ diff )) {return true;} $ relation = 'or' and! Empty ($ list); // when either or is passed, the permission is true $ relation = 'and' and empty ($ diff ); // when and, $ name and $ list are completely equal, the permission is true.
3. obtain the permission list:
$ AuthList = $ this-> getAuthList ($ uid, $ type); // obtain the list of all valid rules to be verified by the user.
The main process is as follows:
Get user group
$groups = $this->getGroups($uid);//SELECT `rules` FROM think_auth_group_access a INNER JOIN think_auth_group g on a.group_id=g.id WHERE ( a.uid='1' and g.status='1' )
The simplified operation is:
SELECT 'rules' FROM think_auth_group where status = '1' AND id = '1' // it is unnecessary to inline in the think_auth_group_access table according to the normal process ....!
Obtain the id of the think_auth_rule rule table saved in the field of the user group rules rule field.
$ Ids is the id array that the $ groups variable is converted:
$map = array( 'id' => array('in', $ids), 'type' => $type, 'status' => 1,);
Obtain the rule information in the think_auth_rule table, and then cyclically:
Foreach ($ rules as $ rule) {if (! Empty ($ rule ['condition']) {// perform verification based on condition $ user = $ this-> getUserInfo ($ uid); // obtain user information, one-dimensional array $ command = preg_replace ('/\ {(\ w *?) \}/',' $ User [\ '\ 1 \'] ', $ rule ['condition']); // dump ($ command ); // debug @ (eval ('$ condition = ('. $ command. '); if ($ condition) {$ authList [] = strtolower ($ rule ['name']);} else {// record $ authList [] = strtolower ($ rule ['name']) if (! Empty ($ rule ['condition']) {// verify the condition
Here we can understand that getUserInfo will get the table name corresponding to the configuration file AUTH_USER to find the user information.
Key points:
$command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $rule['condition']);@(eval('$condition=(' . $command . ');'));
'/\ {(\ W *?) \}/Can be viewed as the string to be matched: {String}, then {String} will be replaced with $ user ['string']
$ Command = $ user ['string']
If
$rule['condition'] = '{age}';$command =$user['age']$rule['condition'] = '{age} > 5';$command =$user['age'] > 10@(eval('$condition=(' . $command . ');'));
That is:
$condition=($user['age'] > 10);
The following code is added as an authorization list if it is true.
if ($condition) { $authList[] = strtolower($rule['name']);}