CakePHP基本身份验证和jQuery

I'm trying to implement Basic Authentication in CakePHP with an application written entirely in jQuery. I was going to use OAuth2, but got fed up with the added complexity and seen as this application will be the only thing using the API, Basic Auth should be sufficient.

The login method looks like:

login: function(username, password) {    
    $.ajax({
        type: 'GET',
        url: 'http://api.domain.com/login',
        beforeSend : function(xhr) {
            var base64 = $.base64.encode(username + ':' + password);
            xhr.setRequestHeader("Authorization", "Basic " + base64);
        },
        dataType: 'jsonp',
        success: function(data) {
            if( data.response.status == 'error' ) {
                alert(data.response.message);
            } else {                
                // Save some sort of session                   
            }
        },
        error: function(a,b,c) {
            console.log(a,b,c);
        }
    });        
}

And on the CakePHP side:

public function login() {    
    if ($this->request->is('get')) {        
        if ($this->Auth->login()) {            
            $response = json_encode(
                array(
                    'meta'=>array(
                        'code'=>$this->response->statusCode(),
                        'in'=>round(microtime(true) - TIME_START, 4)
                    ),
                    'response'=>array(
                        'status'=>'success',
                        'message'=>'successfully logged in'
                    )
                )
            );                
        } else {   
            $response = json_encode(
                array(
                    'meta'=>array(
                        'code'=>$this->response->statusCode(),
                        'in'=>round(microtime(true) - TIME_START, 4)
                    ),
                    'response'=>array(
                        'status'=>'error',
                        'message'=>'incorrect login details'
                    )
                )
            );   
        }           
        // Handle JSONP
        if(isset($_GET['callback'])) {
            $response = $_GET['callback'] . '(' . $response . ')';
        }       
        // Return JSON
        $this->autoRender = false;
        $this->response->type('json');
        $this->response->body($response);           
    }       
}
  1. How do I save the user login details? As I can't create a session because the JavaScript MIGHT not be running on the same server (as it could be an external application, mobile app, etc.) The data WILL be being sent over SSL, but I'm not sure how I can remember user details, so the user doesn't have to keep logging in. As far as I know Basic Authentication is supposed to be stateless... so no cookies or sessions will even exist. Can anyone shed light on this?

Update: After doing some more research into this, I've found that the username and password needs sending with each request... so in effect there NEVER is a session or cookie. But I'd need to store this information somewhere? Otherwise the user would be logging in after every request on the page right?

  1. Once the user has logged in and is now authenticated... how can I make requests to data and handle the authentication to make sure the correct user has access, and if they create data that is created as them. As in OAuth2, I would have an access_token I could just pass to access data, but in Basic Auth, you don't have a token. And because there is no session, I can't access the logged in users information. So how do I do this?

  2. According to the CakePHP docs, you don't need a login method (for Basic Auth) in CakePHP 2.4+ so how exactly does the user login from the Client side and what controller method would I talk to when passing the username and password?

Update: When trying to access the login method based on my code above, I get the prompt for a username and password... but this is an allowed method! Any ideas why? As it prevents my JavaScript from sending the request as the endpoint can never be accessed. Also if I login using the prompt I remain logged in even if I visit the logout method or clear all my sessions/caches in the browser. So how do I delete a users login?

Any help to point me in the right direction would be much appreciated, as it feels I'm completely misunderstanding the way Basic Auth works... Some examples would be awesome!

Update 2:

According to the PHP Docs, the following is the way to check if a user is logged in or not and show a message if they cancel. The information is also stored without ANY USE of a session! So how does this same principle apply to CakePHP? For example, how do I show the correct 401 status and a custom message, how is the logged in user info stored in CakePHP if it's based on this?

<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Text to send if user hits Cancel button';
    exit;
} else {
    echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
}
?>

2个回答

Although Basic Authentication is stateless but according to CakePHP documentation:

Clients using Basic Authentication must support cookies. Since AuthComponent identifies users based on Session contents, clients using Basic Auth must support cookies.

http://api.cakephp.org/2.5/class-BasicAuthenticate.html

But:

Also you can set AuthComponent::$sessionKey to false to ensure AuthComponent doesn’t try to read user info from session. Stateless authentication will re-verify the user’s credentials on each request, this creates a small amount of additional overhead, but allows clients that to login in without using cookies.

http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#using-digest-and-basic-authentication-for-logging-in

Your AppController should be like this:

class AppController extends Controller {

    public $components = array('Auth', 'Session');

    public function beforeFilter() {
        $this->Auth->authorize = array('Controller');
        $this->Auth->authenticate = array('Basic');
        $this->Auth->sessionKey = false;
    }
}

You may also want to use $this->Auth->unauthorizedRedirect = false;. By default unauthorized user is redirected to the referrer URL or AuthComponent::$loginAction or ‘/’. If unauthorizedRedirect is set to false a ForbiddenException exception is thrown instead of redirecting.

And then in every controller you must have isAuthorized() method where you authorize users according to their roles the same way you would do with usual Form Authentication. F.ex.:

public function isAuthorized($user) {
   if (isset($user['role']) && ($user['role'] == 'admin')) {
     return true;
   }
   return false;
}

Because basic and digest authentication don’t require an initial POST or a form so if using only basic / digest authenticators you don’t require a login action in your controller.

http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#using-digest-and-basic-authentication-for-logging-in

That means you do not need to call Users::login() explicitly and when the user tries to access URL she will be presented Basic Authentication window where she must enter username and password every time the page is requested if you do not send Basic Authorization header like you do in your Ajax call xhr.setRequestHeader("Authorization", "Basic " + base64);.

If do not want that the user would be presented with such a window on every request you can store the user credentials in a cookie or preferably in the client's local storage (http://www.w3schools.com/html/html5_webstorage.asp) and set "Authorization" header on every request (to any action of any controller).

You can always send back the authenticated user details from your controller to the client this way:

$this->set(array(
     'user' => json_encode($this->Auth->user()),
     '_serialize' => array('user')
));

Probably you can do it from beforeFilter() so that the authenticated user details are send with each response.

dongpanshi2839
dongpanshi2839 API文档中的“使用基本身份验证的客户端必须支持cookie ...”部分是谎言。 BasicAuthenticate现在可以在无状态模式下正常工作。 文档将很快修复。
6 年多之前 回复



可以在没有cookie的情况下使用会话,在每个查询中将其作为参数共享,并作为json响应的值。</ p >


  1. 准备应用程序以将会话ID存储在数据库或缓存 </ p> </ li>

  2. 成功登录ajax后,在json响应中包含sessionID </ p> </ li >

  3. 每个下一个请求必须包含sessionID作为参数,响应还必须包含sessionID </ p> </ li>
    </ ol>

    这是 我该怎么做。</ p>
    </ div>

展开原文

原文

Sessions can be used without cookies, share it as a parameter in the each query, and as the value of json response.

  1. Prepare your application to store sessionID in database or cache

  2. after successful ajax login, in the json response include the sessionID

  3. every next request must contain the sessionID as a parameter, the response must also include a sessionID

This is how I would do.

dpmir1988
dpmir1988 你是对的
6 年多之前 回复
douda5706
douda5706 但Basic Auth不使用会话吗? 它将auth详细信息存储在AUTH_USER和AUTH_PW变量中,并且没有到期时间。
6 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐