diff options
-rw-r--r-- | demos/quickstart/protected/pages/Advanced/Auth.page | 10 | ||||
-rw-r--r-- | framework/Security/TAuthManager.php | 2 | ||||
-rw-r--r-- | framework/Security/TAuthorizationRule.php | 68 | ||||
-rw-r--r-- | framework/Web/Services/TPageService.php | 4 |
4 files changed, 54 insertions, 30 deletions
diff --git a/demos/quickstart/protected/pages/Advanced/Auth.page b/demos/quickstart/protected/pages/Advanced/Auth.page index 1c89e07d..531b8bdf 100644 --- a/demos/quickstart/protected/pages/Advanced/Auth.page +++ b/demos/quickstart/protected/pages/Advanced/Auth.page @@ -56,10 +56,10 @@ Authorization rules for pages are specified in <a href="?page=Configurations.Pag An authorization rule can be either an <tt>allow</tt> rule or a <tt>deny</tt> rule. Each rule consists of four optional properties:
</p>
<ul id="u1" class="block-content">
-<li><tt>pages</tt> - list of comma-separated page names that this rule applies to. If empty or not set, this rule will apply to all pages under the current directory and all its subdirectories recursively.</li>
-<li><tt>users</tt> - list of comma-separated user names that this rule applies to. A character * refers to all users including anonymous/guest user. A character ? refers to anonymous/guest user. And a character @ refers to authenticated users (available since v3.1).</li>
-<li><tt>roles</tt> - list of comma-separated user roles that this rule applies to.</li>
-<li><tt>verb</tt> - page access method that this rule applies to. It can be either <tt>get</tt> or <tt>post</tt>. If empty or not set, the rule applies to both methods.</li>
+<li><tt>pages</tt> - list of comma-separated page names that this rule applies to. If empty, not set or wildcard '*', this rule will apply to all pages under the current directory and all its subdirectories recursively.</li>
+<li><tt>users</tt> - list of comma-separated user names that this rule applies to. If empty, not set or wildcard '*', this rule will apply to all users including anonymous/guest user. A character ? refers to anonymous/guest user. And a character @ refers to authenticated users (available since v3.1).</li>
+<li><tt>roles</tt> - list of comma-separated user roles that this rule applies to. If empty, not set or wildcard '*', this rule will apply to all user roles.</li>
+<li><tt>verb</tt> - page access method that this rule applies to. It can be either <tt>get</tt> or <tt>post</tt>. If empty, not set or wildcard '*', the rule will apply to both methods.</li>
</ul>
<p id="720558" class="block-content">
@@ -80,7 +80,7 @@ Since version 3.1.1, the <tt>pages</tt> attribute in the authorization rules can </p>
<p class="block-content">
-Also introduced in version 3.1.1 are IP rules. They are specified by a new attribute <tt>ip</tt> in authorization rules. The IP rules are used to determine if an authorization rule aplies to an end-user according to his IP address. One can list a few IPs together, separated by comma ','. Wildcard '*' can be used in the rules. For example, <tt>ip="192.168.0.2, 192.168.1.*"</tt> means the rule applies to users whose IP address is 192.168.0.2 or 192.168.1.*. The latter matches any host in the subnet 192.168.1.
+Also introduced in version 3.1.1 are IP rules. They are specified by a new attribute <tt>ips</tt> in authorization rules. The IP rules are used to determine if an authorization rule aplies to an end-user according to his IP address. One can list a few IPs together, separated by comma ','. Wildcard '*' can be used in the rules. For example, <tt>ips="192.168.0.2, 192.168.1.*"</tt> means the rule applies to users whose IP address is 192.168.0.2 or 192.168.1.*. The latter matches any host in the subnet 192.168.1. If the attribute 'ips' is empty, not set or wildcard '*', the corresponding rule will apply to requests coming from any host address.
</p>
<h2 id="5504">Using <tt>TUserManager</tt></h2>
diff --git a/framework/Security/TAuthManager.php b/framework/Security/TAuthManager.php index cbad51dc..fcbb64d2 100644 --- a/framework/Security/TAuthManager.php +++ b/framework/Security/TAuthManager.php @@ -251,7 +251,7 @@ class TAuthManager extends TModule $application=$this->getApplication();
if($this->hasEventHandler('OnAuthorize'))
$this->raiseEvent('OnAuthorize',$this,$application);
- if(!$application->getAuthorizationRules()->isUserAllowed($application->getUser(),$application->getRequest()->getRequestType()))
+ if(!$application->getAuthorizationRules()->isUserAllowed($application->getUser(),$application->getRequest()->getRequestType(),$application->getRequest()->getUserHostAddress()))
{
$application->getResponse()->setStatusCode(401);
$application->completeRequest();
diff --git a/framework/Security/TAuthorizationRule.php b/framework/Security/TAuthorizationRule.php index 42a11412..bdc0e902 100644 --- a/framework/Security/TAuthorizationRule.php +++ b/framework/Security/TAuthorizationRule.php @@ -85,6 +85,9 @@ class TAuthorizationRule extends TComponent $this->_everyone=false;
$this->_guest=false;
$this->_authenticated=false;
+
+ if(trim($users)==='')
+ $users='*';
foreach(explode(',',$users) as $user)
{
if(($user=trim(strtolower($user)))!=='')
@@ -102,16 +105,24 @@ class TAuthorizationRule extends TComponent $this->_users[]=$user;
}
}
+
+ if(trim($roles)==='')
+ $roles='*';
foreach(explode(',',$roles) as $role)
{
if(($role=trim(strtolower($role)))!=='')
$this->_roles[]=$role;
}
- $verb=trim(strtolower($verb));
- if($verb==='' || $verb==='get' || $verb==='post')
+
+ if(($verb=trim(strtolower($verb)))==='')
+ $verb='*';
+ if($verb==='*' || $verb==='get' || $verb==='post')
$this->_verb=$verb;
else
throw new TInvalidDataValueException('authorizationrule_verb_invalid',$verb);
+
+ if(trim($ipRules)==='')
+ $ipRules='*';
foreach(explode(',',$ipRules) as $ipRule)
{
if(($ipRule=trim($ipRule))!=='')
@@ -185,38 +196,50 @@ class TAuthorizationRule extends TComponent }
/**
+ * @param IUser the user object
+ * @param string the request verb (GET, PUT)
+ * @param string the request IP address
* @return integer 1 if the user is allowed, -1 if the user is denied, 0 if the rule does not apply to the user
*/
- public function isUserAllowed(IUser $user,$verb)
+ public function isUserAllowed(IUser $user,$verb,$ip)
{
- $decision=($this->_action==='allow')?1:-1;
- if($this->_verb==='' || strcasecmp($verb,$this->_verb)===0)
- {
- if(!$this->isHostAddressMatched())
- return 0;
- if($this->_everyone || ($this->_guest && $user->getIsGuest()) || ($this->_authenticated && !$user->getIsGuest()))
- return $decision;
- if(in_array(strtolower($user->getName()),$this->_users))
- return $decision;
- foreach($this->_roles as $role)
- if($user->isInRole($role))
- return $decision;
- }
- return 0;
+ if($this->isVerbMatched($verb) && $this->isIpMatched($ip) && $this->isUserMatched($user) && $this->isRoleMatched($user))
+ return ($this->_action==='allow')?1:-1;
+ else
+ return 0;
}
- private function isHostAddressMatched()
+ private function isIpMatched($ip)
{
if(empty($this->_ipRules))
return 1;
- $ip=Prado::getApplication()->getRequest()->getUserHostAddress();
foreach($this->_ipRules as $rule)
{
- if($rule===$ip || (($pos=strpos($rule,'*'))!==false && strncmp($ip,$rule,$pos)===0))
+ if($rule==='*' || $rule===$ip || (($pos=strpos($rule,'*'))!==false && strncmp($ip,$rule,$pos)===0))
return 1;
}
return 0;
}
+
+ private function isUserMatched($user)
+ {
+ return ($this->_everyone || ($this->_guest && $user->getIsGuest()) || ($this->_authenticated && !$user->getIsGuest()));
+ }
+
+ private function isRoleMatched($user)
+ {
+ foreach($this->_roles as $role)
+ {
+ if($role==='*' || $user->isInRole($role))
+ return true;
+ }
+ return false;
+ }
+
+ private function isVerbMatched($verb)
+ {
+ return ($this->_verb==='*' || strcasecmp($verb,$this->_verb)===0);
+ }
}
@@ -235,16 +258,17 @@ class TAuthorizationRuleCollection extends TList /**
* @param IUser the user to be authorized
* @param string verb, can be empty, 'post' or 'get'.
+ * @param string the request IP address
* @return boolean whether the user is allowed
*/
- public function isUserAllowed($user,$verb)
+ public function isUserAllowed($user,$verb,$ip)
{
if($user instanceof IUser)
{
$verb=strtolower(trim($verb));
foreach($this as $rule)
{
- if(($decision=$rule->isUserAllowed($user,$verb))!==0)
+ if(($decision=$rule->isUserAllowed($user,$verb,$ip))!==0)
return ($decision>0);
}
return true;
diff --git a/framework/Web/Services/TPageService.php b/framework/Web/Services/TPageService.php index ced01641..568e9a40 100644 --- a/framework/Web/Services/TPageService.php +++ b/framework/Web/Services/TPageService.php @@ -653,7 +653,7 @@ class TPageConfiguration extends TComponent {
$patterns=$node->getAttribute('pages');
$ruleApplies=false;
- if(empty($patterns)) // null or empty string
+ if(empty($patterns) || trim($patterns)==='*') // null or empty string
$ruleApplies=true;
else
{
@@ -681,7 +681,7 @@ class TPageConfiguration extends TComponent }
}
if($ruleApplies)
- $rules[]=new TAuthorizationRule($node->getTagName(),$node->getAttribute('users'),$node->getAttribute('roles'),$node->getAttribute('verb'),$node->getAttribute('ip'));
+ $rules[]=new TAuthorizationRule($node->getTagName(),$node->getAttribute('users'),$node->getAttribute('roles'),$node->getAttribute('verb'),$node->getAttribute('ips'));
}
$this->_rules=array_merge($rules,$this->_rules);
}
|