| 1 |
lars |
1 |
<com:TContent ID="body" >
|
|
|
2 |
|
|
|
3 |
<h1 id="5501">Authentication and Authorization</h1>
|
|
|
4 |
<p id="720549" class="block-content">
|
|
|
5 |
Authentication is a process of verifying whether someone is who he claims he is. It usually involves a username and a password, but may include any other methods of demonstrating identity, such as a smart card, fingerprints, etc.
|
|
|
6 |
</p>
|
|
|
7 |
<p id="720550" class="block-content">
|
|
|
8 |
Authorization is finding out if the person, once identified, is permitted to manipulate specific resources. This is usually determined by finding out if that person is of a particular role that has access to the resources.
|
|
|
9 |
</p>
|
|
|
10 |
|
|
|
11 |
<h2 id="5502">How PRADO Auth Framework Works</h2>
|
|
|
12 |
<p id="720551" class="block-content">
|
|
|
13 |
PRADO provides an extensible authentication/authorization framework. As described in <a href="?page=Fundamentals.Applications">application lifecycles</a>, <tt>TApplication</tt> reserves several lifecycles for modules responsible for authentication and authorization. PRADO provides the <tt>TAuthManager</tt> module for such purposes. Developers can plug in their own auth modules easily. <tt>TAuthManager</tt> is designed to be used together with <tt>TUserManager</tt> module, which implements a read-only user database.
|
|
|
14 |
</p>
|
|
|
15 |
<p id="720552" class="block-content">
|
|
|
16 |
When a page request occurs, <tt>TAuthManager</tt> will try to restore user information from session. If no user information is found, the user is considered as an anonymous or guest user. To facilitate user identity verification, <tt>TAuthManager</tt> provides two commonly used methods: <tt>login()</tt> and <tt>logout()</tt>. A user is logged in (verified) if his username and password entries match a record in the user database managed by <tt>TUserManager</tt>. A user is logged out if his user information is cleared from session and he needs to re-login if he makes new page requests.
|
|
|
17 |
</p>
|
|
|
18 |
<p id="720553" class="block-content">
|
|
|
19 |
During <tt>Authorization</tt> application lifecycle, which occurs after <tt>Authentication</tt> lifecycle, <tt>TAuthManager</tt> will verify if the current user has access to the requested page according to a set of authorization rules. The authorization is role-based, i.e., a user has access to a page if 1) the page explicitly states that the user has access; 2) or the user is of a particular role that has access to the page. If the user does not have access to the page, <tt>TAuthManager</tt> will redirect user browser to the login page which is specified by <tt>LoginPage</tt> property.
|
|
|
20 |
</p>
|
|
|
21 |
|
|
|
22 |
<h2 id="5503">Using PRADO Auth Framework</h2>
|
|
|
23 |
<p id="720554" class="block-content">
|
|
|
24 |
To enable PRADO auth framework, add the <tt>TAuthManager</tt> module and <tt>TUserManager</tt> module to <a href="?page=Configurations.AppConfig">application configuration</a>,
|
|
|
25 |
</p>
|
|
|
26 |
<com:TTextHighlighter Language="xml" CssClass="source block-content" id="code1">
|
|
|
27 |
<service id="page" class="TPageService">
|
|
|
28 |
<modules>
|
|
|
29 |
<module id="auth" class="System.Security.TAuthManager"
|
|
|
30 |
UserManager="users" LoginPage="UserLogin" />
|
|
|
31 |
<module id="users" class="System.Security.TUserManager"
|
|
|
32 |
PasswordMode="Clear">
|
|
|
33 |
<user name="demo" password="demo" />
|
|
|
34 |
<user name="admin" password="admin" />
|
|
|
35 |
</module>
|
|
|
36 |
</modules>
|
|
|
37 |
</service>
|
|
|
38 |
</com:TTextHighlighter>
|
|
|
39 |
<p id="720555" class="block-content">
|
|
|
40 |
In the above, the <tt>UserManager</tt> property of <tt>TAuthManager</tt> is set to the <tt>users</tt> module which is <tt>TUserManager</tt>. Developers may replace it with a different user management module that is derived from <tt>TUserManager</tt>.
|
|
|
41 |
</p>
|
|
|
42 |
<p id="720556" class="block-content">
|
|
|
43 |
Authorization rules for pages are specified in <a href="?page=Configurations.PageConfig">page configurations</a> as follows,
|
|
|
44 |
</p>
|
|
|
45 |
<com:TTextHighlighter Language="xml" CssClass="source block-content" id="code2">
|
|
|
46 |
<authorization>
|
|
|
47 |
<allow pages="PageID1,PageID2"
|
|
|
48 |
users="User1,User2"
|
|
|
49 |
roles="Role1" />
|
|
|
50 |
<deny pages="PageID1,PageID2"
|
|
|
51 |
users="?"
|
|
|
52 |
verb="post" />
|
|
|
53 |
</authorization>
|
|
|
54 |
</com:TTextHighlighter>
|
|
|
55 |
<p id="720557" class="block-content">
|
|
|
56 |
An authorization rule can be either an <tt>allow</tt> rule or a <tt>deny</tt> rule. Each rule consists of four optional properties:
|
|
|
57 |
</p>
|
|
|
58 |
<ul id="u1" class="block-content">
|
|
|
59 |
<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>
|
|
|
60 |
<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>
|
|
|
61 |
<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>
|
|
|
62 |
<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>
|
|
|
63 |
</ul>
|
|
|
64 |
|
|
|
65 |
<p id="720558" class="block-content">
|
|
|
66 |
When a page request is being processed, a list of authorization rules may be available. However, only the <i>first effective</i> rule <i>matching</i> the current user will render the authorization result.
|
|
|
67 |
</p>
|
|
|
68 |
<ul id="u2" class="block-content">
|
|
|
69 |
<li>Rules are ordered bottom-up, i.e., the rules contained in the configuration of current page folder go first. Rules in configurations of parent page folders go after.</li>
|
|
|
70 |
<li>A rule is effective if the current page is in the listed pages of the rule AND the current user action (<tt>get</tt> or <tt>post</tt>) is in the listed actions.</li>
|
|
|
71 |
<li>A rule matching occurs if the current user name is in the listed user names of an <i>effective</i> rule OR if the user's role is in the listed roles of that rule.</li>
|
|
|
72 |
<li>If no rule matches, the user is authorized.</li>
|
|
|
73 |
</ul>
|
|
|
74 |
<p id="720559" class="block-content">
|
|
|
75 |
In the above example, anonymous users will be denied from posting to <tt>PageID1</tt> and <tt>PageID2</tt>, while <tt>User1</tt> and <tt>User2</tt> and all users of role <tt>Role1</tt> can access the two pages (in both <tt>get</tt> and <tt>post</tt> methods).
|
|
|
76 |
</p>
|
|
|
77 |
<com:SinceVersion Version="3.1.1" />
|
|
|
78 |
<p class="block-content">
|
|
|
79 |
Since version 3.1.1, the <tt>pages</tt> attribute in the authorization rules can take relative page paths with wildcard '*'. For example, <tt>pages="admin.Home"</tt> refers to the <tt>Home</tt> page under the <tt>admin</tt> directory, and <tt>pages="admin.*"</tt> would refer to all pages under the <tt>admin</tt> directory and subdirectories.
|
|
|
80 |
</p>
|
|
|
81 |
|
|
|
82 |
<p class="block-content">
|
|
|
83 |
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.
|
|
|
84 |
</p>
|
|
|
85 |
|
|
|
86 |
<h2 id="5504">Using <tt>TUserManager</tt></h2>
|
|
|
87 |
<p id="720560" class="block-content">
|
|
|
88 |
As aforementioned, <tt>TUserManager</tt> implements a read-only user database. The user information are specified in either application configuration or an external XML file.
|
|
|
89 |
</p>
|
|
|
90 |
<p id="720561" class="block-content">
|
|
|
91 |
We have seen in the above example that two users are specified in the application configuration. Complete syntax of specifying the user and role information is as follows,
|
|
|
92 |
</p>
|
|
|
93 |
<com:TTextHighlighter Language="xml" CssClass="source block-content" id="code3">
|
|
|
94 |
<user name="demo" password="demo" roles="demo,admin" />
|
|
|
95 |
<role name="admin" users="demo,demo2" />
|
|
|
96 |
</com:TTextHighlighter>
|
|
|
97 |
<p id="720562" class="block-content">
|
|
|
98 |
where the <tt>roles</tt> attribute in <tt>user</tt> element is optional. User roles can be specified in either the <tt>user</tt> element or in a separate <tt>role</tt> element.
|
|
|
99 |
</p>
|
|
|
100 |
|
|
|
101 |
<h2 id="5505">Using <tt>TDbUserManager</tt></h2>
|
|
|
102 |
<p id="720563" class="block-content">
|
|
|
103 |
<tt>TDbUserManager</tt> is introduced in v3.1.0. Its main purpose is to simplify the task of managing user accounts that are stored in a database. It requires developers to write a user class that represents the necessary information for a user account. The user class must extend from <tt>TDbUser</tt>.
|
|
|
104 |
</p>
|
|
|
105 |
<p id="720564" class="block-content">
|
|
|
106 |
To use <tt>TDbUserManager</tt>, configure it in the application configuration like following:
|
|
|
107 |
</p>
|
|
|
108 |
<com:TTextHighlighter Language="xml" CssClass="source block-content" id="code4">
|
|
|
109 |
<module id="db"
|
|
|
110 |
class="System.Data.TDataSourceConfig" ..../>
|
|
|
111 |
<module id="users"
|
|
|
112 |
class="System.Security.TDbUserManager"
|
|
|
113 |
UserClass="Path.To.MyUserClass"
|
|
|
114 |
ConnectionID="db" />
|
|
|
115 |
<module id="auth"
|
|
|
116 |
class="System.Security.TAuthManager"
|
|
|
117 |
UserManager="users" LoginPage="Path.To.LoginPage" />
|
|
|
118 |
</com:TTextHighlighter>
|
|
|
119 |
|
|
|
120 |
</p>
|
|
|
121 |
<p id="720565" class="block-content">
|
|
|
122 |
In the above, <tt>UserClass</tt> specifies what class will be used to create user instance. The class must extend from <tt>TDbUser</tt>. <tt>ConnectionID</tt> refers to the ID of a <tt>TDataSourceConfig</tt> module which specifies how to establish database connection to retrieve user information.
|
|
|
123 |
</p>
|
|
|
124 |
<p id="720566" class="block-content">
|
|
|
125 |
The user class has to implement the two abstract methods in <tt>TDbUser</tt>: <tt>validateUser()</tt> and <tt>createUser()</tt>. Since user account information is stored in a database, the user class may make use of its <tt>DbConnection</tt> property to reach the database.
|
|
|
126 |
</p>
|
|
|
127 |
<com:SinceVersion Version="3.1.1" />
|
|
|
128 |
<p id="720567" class="block-content">
|
|
|
129 |
Since 3.1.1, <tt>TAuthManager</tt> provides support to allow remembering login by setting <tt>AllowAutoLogin</tt> to true. Accordingly, <tt>TDbUser</tt> adds two methods to facilitate the implementation of this feature. In particular, two new methods are introduced: <tt>createUserFromCookie()</tt> and <tt>saveUserToCookie()</tt>. Developers should implement these two methods if remembering login is needed. Below is a sample implementation:
|
|
|
130 |
</p>
|
|
|
131 |
<com:TTextHighlighter Language="php" CssClass="source block-content" id="code5">
|
|
|
132 |
public function createUserFromCookie($cookie)
|
|
|
133 |
{
|
|
|
134 |
if(($data=$cookie->Value)!=='')
|
|
|
135 |
{
|
|
|
136 |
$application=Prado::getApplication();
|
|
|
137 |
if(($data=$application->SecurityManager->validateData($data))!==false)
|
|
|
138 |
{
|
|
|
139 |
$data=unserialize($data);
|
|
|
140 |
if(is_array($data) && count($data)===3)
|
|
|
141 |
{
|
|
|
142 |
list($username,$address,$token)=$data;
|
|
|
143 |
$sql='SELECT passcode FROM user WHERE LOWER(username)=:username';
|
|
|
144 |
$command=$this->DbConnection->createCommand($sql);
|
|
|
145 |
$command->bindValue(':username',strtolower($username));
|
|
|
146 |
if($token===$command->queryScalar() && $token!==false && $address=$application->Request->UserHostAddress)
|
|
|
147 |
return $this->createUser($username);
|
|
|
148 |
}
|
|
|
149 |
}
|
|
|
150 |
}
|
|
|
151 |
return null;
|
|
|
152 |
}
|
|
|
153 |
|
|
|
154 |
public function saveUserToCookie($cookie)
|
|
|
155 |
{
|
|
|
156 |
$application=Prado::getApplication();
|
|
|
157 |
$username=strtolower($this->Name);
|
|
|
158 |
$address=$application->Request->UserHostAddress;
|
|
|
159 |
$sql='SELECT passcode FROM user WHERE LOWER(username)=:username';
|
|
|
160 |
$command=$this->DbConnection->createCommand($sql);
|
|
|
161 |
$command->bindValue(':username',strtolower($username));
|
|
|
162 |
$token=$command->queryScalar();
|
|
|
163 |
$data=array($username,$address,$token);
|
|
|
164 |
$data=serialize($data);
|
|
|
165 |
$data=$application->SecurityManager->hashData($data);
|
|
|
166 |
$cookie->setValue($data);
|
|
|
167 |
}
|
|
|
168 |
</com:TTextHighlighter>
|
|
|
169 |
|
|
|
170 |
<div class="last-modified">$Id: Auth.page 2245 2007-09-26 13:22:02Z xue $</div></com:TContent>
|