dpdhnd3577 2017-06-05 02:30
浏览 41

用户身份验证会话 - Angular + API

Im trying to put together an authentication process for user login/access control for my Angular JS boilerplate and API built in PHP.

Ive read alot about some of the various methods/techniques like JWS tokens, oAuth, Sessions, Cookies etc.

It seems there are alot of options and methods, some of which seem redundant.

The approach Ive cobbled together is as follows:

(all code is abbreviated for clarity - dependencies, supporting code, & error handling have been omitted)

AUTHENTICATION:

Client Side

1) User enters username/password credentials into login form and submits the data.

2) A request containing the login data is sent to my API on submit:

$http.post('https://my.api/login', loginData).then(function(res){ // send request

    if(res.data.response.status > 0){                             // success

        $localStorage.session = {                                 // create session object
            uid: res.data.session.user_id,
            urole: res.data.session.user_role,
            token: res.data.session.token
        };

    } else console.log('login failed');                           // failed

});

Server Side

// check that user exists
$user = db_select('SELECT * FROM users WHERE username=?',array($username));
if(count($user)>0){

    if(validate_str($pw, $user['password'])) { // validate hashed password

        $res['session'] = sessionCreate($user[0]['id']);

    }

}

sessionCreate() is basically creates DB record storing a generated token, expiration time, and user ID.

$expiry = add2Date(now(),'+2 hours'); // session expires in 2 hours
$token = rando(50);                   // token is a random alpha-numeric 50 char in length

$query = compileINSERT(array('user_id'=>$user_id,'token'=>$token,'expiry'=>$expiry),'user_session');
$session_id = db_process($query['sql'],$query['val']);

if($session_id>0) return(validateSession($token));

validateSession() is used later to validate a session but used here to return the newly created session.

As shown above (Client Side), a successful response results in the returned session to be saved as an object in $localStorage.

ACCESS CONTROL:

Client Side

Once a user has logged-in, access control is handled in the resolve object of UI-Router using a service.

There are two components to access control: validating that the session exists and is valid, and validating that the $stateParams slug of page being attempted to access matches the user session.

.state('base.user', {

    url:'/user/:id',
    templateUrl: 'views/user.html',
    controller: 'userCtrl',
    resolve: { // authenticate user and check access control

        authenticate: function ($q, $state, $timeout, $localStorage, $stateParams, AuthService){
            AuthService.validate($localStorage.session.token).then(function(res){ 
                if(res.data.response.status!==1 
                || !AuthService.access($localStorage.session.uid, $stateParams.id)) { 
                    $timeout(function() { $state.go('base.notfound') });
                    return $q.reject();
                } else return $q.resolve();
            });
        } 

    }
})

AuthService.validate() and AuthService.access() are both defined in the service:

.service('AuthService', function($http){

    this.validate = function(token){

        // send token to API 
        $http.get('http://my.api/validate/'+token); 
    }

    this.access = function(uid, stateparam){ 

        // make sure session user_id matches URI slug being accessed
        if(Number(uid)===Number(stateparam)) return true;
        else return false;
    }

})

Server Side

On the back-end, the token is used to validate the session:

$token = $this->req['slug'][0];

if(!empty($token)){ 

    $result = validateSession($token);

    if($result['status']>0) $res['session'] = $result['session'];
    else if($result['status']<0) $_response['error'][] = 'session expired';
    else if($result['status']===0) $_response['error'][] = 'session does not exist';

} else $_response['error'][] = 'token not set';

And finally, validateSession() is as follows:

function validateSession($token){

    $response = array('status'=>0,'session'=>array());

    // fetch the session using token
    $session = db_select('SELECT * FROM user_session WHERE token=? ORDER BY expiry',array($token))[0];
    if(!empty($session)) {

        $time_to_expiry = datetimeDiff($session['expiry'],now());
        if($time_to_expiry['invert']==0)    $response['status'] = -1;   // session exists but is expired
        else                               $response['status'] = 1;   // session valid

        $response['session'] = $session;
    } 

    return($response); // return session or an error
}

SUMMARY

To summarize, authentication and validation as I have written is as follows:

Authentication:

1) user logs in

2) login data is sent to API

3) username/password pair is validated

4) a database record containing the user id, expiry, and unique generated token is created

5) session data is returned in the response JSON and stored in local storage

Access Control:

1) User attempts to access a restricted page

2) token from local storage session data is sent to API

3) API checks whether session with token exists in DB and has not expired

4) API returns an valid/invalid status

additionally,

5) user id from local storage session data is checked against the URI slug for the restricted page (to prevent any authenticated user from accessing any other authenticated user's content)

MY QUESTIONS (finally)

I realize all of the above is a bit naive and just seems too simplistic so here are the questions:

1) I am sending my token in the URL rather than in the request header, what are the drawback (if any) of doing this. Why should the token be sent in the request header?

2) I am not using cookies, however all the pieces seem to be there for a functional authentication/access control protocol. Where would cookie fit in above example?

3) What are some exploits that can be used to bypass the system above?

4) What are some best-practices that I am not holding to in the above system?

5) Any input & critique would be appreciated.

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 processing提取音乐节奏
    • ¥15 python进程启动打包问题
    • ¥15 gg加速器加速游戏时,提示不是x86架构
    • ¥15 python按要求编写程序
    • ¥15 Python输入字符串转化为列表排序具体见图,严格按照输入
    • ¥20 XP系统在重新启动后进不去桌面,一直黑屏。
    • ¥15 opencv图像处理,需要四个处理结果图
    • ¥15 无线移动边缘计算系统中的系统模型
    • ¥15 深度学习中的画图问题
    • ¥15 java报错:使用mybatis plus查询一个只返回一条数据的sql,却报错返回了1000多条