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);
  		}
  | 
