发新话题
打印

从Auth的用法学习CakePHP中的控制器组件

从Auth的用法学习CakePHP中的控制器组件

作者:老王

Auth组件是CakePHP1.2新加入的功能,用于登录验证等方面很方便,不过因为还没有相应的文档,所以只能自己啃源代码来猜测使用方法。

大致工作方式是这样的:

Auth缺省认为你的用户模型为User,相应的表就是users,相应的用户名,密码字段是username和password
复制内容到剪贴板
代码:
var $userModel = 'User';
var $fields = array('username' => 'username', 'password' => 'password');
所有这些缺省值都是可以修改的,不过在哪里改是值得商榷的,肯定不能直接修改源文件,那样等你升级的时候麻烦就大了,通过查看dispatcher.php文件,我们发现在beforeFilter方法执行后才进行组件的初始化,所以在beforeFilter里修改组件的缺省值是比较合适的。

相应的代码大致类似这样:
复制内容到剪贴板
代码:
class AppController extends Controller
{
        function beforeFilter()
        {
            $this->Auth->userModel = 'User';
            $this->Auth->loginAction = '/users/login';
            $this->Auth->fields = array('username' => 'username', 'password' => 'password');

......
在我们的登录方法中,我们不用做任何操作,因为Auth会根据设置自动进行合法性验证。如果Auth发现你尚未登录,会根据你的设置推测出登录地址,并重定向到此地址,比如上面设置,CakePHP会推测登录地址为/users/login(这也是缺省地址)。

不过这中间还是有一个地方会很烦人,那就是Auth组件缺省对密码的加密方式不是可配置的,大致如下:
复制内容到剪贴板
代码:
function password($password) {
        return Security::hash(CAKE_SESSION_STRING . $password);
}
这样的硬编码当然没有通用性,毕竟多数情况我们使用的是md5方式,解决这个问题的方式大致如下:

拷贝/cake/libs/controller/components/auth.php文件到/app/controller/components/auth.php目录下,然后修改
复制内容到剪贴板
代码:
function password($password) {
        return md5($password);
}
即可,因为CakePHP加载组件的时候会优先从app目录加载,所以这个方法是可行的,但是多少还是有点不舒服,更好的方法是我们自定义一个组件,这个组件继承Auth组件,并在其中覆盖父类的password()方法,这样就顺眼多了。

还有一点,因为我们的控制器里,可能并不是每个action都需要auth验证,所有有时候我们需要将一些action排除在外,方法是在相应的控制器里加入类似下面的代码:
复制内容到剪贴板
代码:
function beforeFilter()
{
    //actions we allow without authentication, you can also put them in the app_controller.php
    $this->Auth->allow('index', 'register', 'login', 'logout');
}
可以参考此链接

TOP

在cakephp 1.2的view下的.ctp文件中如何不通过helper直接使用控制器set过来的数据?
比如说在控制器里边
$this->set( array('key' => 'value') );
然后在.ctp文件中应该如何打印出这个key的value呢?
努力为phpres做贡献
时刻准备着,当机会来临时你就成功了
打好基础,增加社会经验
资深技术工程师是我的梦想
承接各种团体网站外包服务和各种it技术培训
准备申请AJAX版大,希望大家支持~~

TOP

你这个问题似乎就不是问题。打印这个值echo $key就好了。

TOP

谢谢老王!
那请问如果是$this->data里边自动render过去的数据呢?
似乎用键名的方法调用不成功
努力为phpres做贡献
时刻准备着,当机会来临时你就成功了
打好基础,增加社会经验
资深技术工程师是我的梦想
承接各种团体网站外包服务和各种it技术培训
准备申请AJAX版大,希望大家支持~~

TOP

发现在.ctp 文件中$this->data['Model']['field']可以打出来。
就是写起来麻烦了点,有更好的办法吗?
努力为phpres做贡献
时刻准备着,当机会来临时你就成功了
打好基础,增加社会经验
资深技术工程师是我的梦想
承接各种团体网站外包服务和各种it技术培训
准备申请AJAX版大,希望大家支持~~

TOP

我觉得没有更简单的方式了,话说回来,我更习惯与在控制器中明确的set要在视图中显示的变量。似乎你对CakePHP的工作原理还不清晰,多看源代码,你就不会有这些疑问了。

如这个视图渲染过程:

控制器的render()方法完成渲染,如果此方法没有在控制器中被显式调用,这dispatcher会自动调用此方法。

并且在控制器的此方法中,会实例化视图对象,并把控制器本身作为构造函数的形参传入。

然后视图对象从控制器中取得需要的变量,如下:
复制内容到剪贴板
代码:
var $__passedVars = array('viewVars', 'action', 'autoLayout', 'autoRender', 'ext', 'base', 'webroot', 'helpers', 'here', 'layout', 'modelNames', 'name', 'pageTitle', 'layoutPath', 'viewPath', 'params', 'data', 'webservices', 'plugin', 'namedArgs', 'argSeparator', 'cacheAction');
这些都会自动从控制器中复制到视图中,也就是说,都可以直接在CTP中echo,当然,这里我们最习惯的还是操作viewVars,也就是控制器中 set出来的视图变量。

TOP

老王非常详细的讲解。
可能是我个人对于减少程序代码有点吹毛求疵,希望程序更加自动化。

最后我还是选择了在app_controller里边重写render方法,在里边把控制器的$this->data自动SET到了.ctp文件中:

if ( !empty($this->data) )
{
foreach ( $this->data as $key => $value )
{
$this->set($key, $value);
}
}
其实我这种做法比较钻牛角尖,也就减少一行$this->set代码。
努力为phpres做贡献
时刻准备着,当机会来临时你就成功了
打好基础,增加社会经验
资深技术工程师是我的梦想
承接各种团体网站外包服务和各种it技术培训
准备申请AJAX版大,希望大家支持~~

TOP

你这样做也相当不错。

为了减少程序代码会思考这么多,足见你是个有完美主义倾向的程序员。

TOP

谢谢老王夸奖,从你的贴子中学到了不少东西。
努力为phpres做贡献
时刻准备着,当机会来临时你就成功了
打好基础,增加社会经验
资深技术工程师是我的梦想
承接各种团体网站外包服务和各种it技术培训
准备申请AJAX版大,希望大家支持~~

TOP

这可以算是夸奖,也可以算是忠告。

说是夸奖,是因为学习需要这样的态度。
说是忠告,是因为对程序员来说,完美主意往往是害人的,因为完美并不存在,我们只要做到“刚刚好”的程度就足矣了。

不过老实说,我也是一个有完美主义倾向的程序员,骨子里的东西,很难改掉。

TOP

发新话题