2015-06-12 99 views
3

我正在使用Laravel 5 Framework開發Android應用程序和RESTful API。 我在登錄活動中遇到了麻煩:流程是用戶詢問第8個字符的代碼,服務器網站向他發送一條SMS。然後用戶可以使用此代碼進行登錄,如密碼。使用Android應用程序的Laravel RESTful API

這是要求一個代碼的代碼:

private void askCode(String mobile) { 
    GsonRequest<String> jsObjRequest = new GsonRequest<String>(
      Request.Method.GET, 
      WebAPIRoute.authGetCode + "/" + mobile, 
      String.class, null, 
      new Response.Listener<String>() { 

       @Override 
       public void onResponse(String code) { 
        txtResponse.setText("Code asked successfully."); 
       } 
      }, 
      new Response.ErrorListener() { 

       @Override 
       public void onErrorResponse(VolleyError volleyError) { 
        Toast.makeText(getBaseContext(), volleyError.getMessage(), Toast.LENGTH_SHORT).show(); 
       } 
      }); 
    this.requestQueue.add(jsObjRequest); 
} 

這REST式API的方法中,以生成代碼:

public function getCode($mobileNum) 
{  
    //genero un numero casuale da mandare con l'sms 
    $code = mt_rand(10000000, 99999999); 

    Session::put('code', $code); 

    sendCode($mobileNum, $code); //send code by SMS 

    return response()->json(array("success"=>true)); 
} 

生成存儲到Laravel的會話的代碼(可配置與文件驅動程序)。 當用戶想要登錄,應用程序調用這個方法:

private void saveUser(final String code, final String mobile, final String name) { 
    HashMap<String, String> params = new HashMap<String, String>(); 

    params.put("nickname", name); 
    params.put("mobile", mobile); 
    params.put("code", code); 

    GsonRequest<String> jsObjRequest = new GsonRequest<String>(
      Request.Method.POST, 
      WebAPIRoute.authValidateCode, 
      String.class, 
      params, 
      new Response.Listener<String>() { 
       @Override 
       public void onResponse(String authtoken) { 
        final Account account = new Account(accountName, mAccountType); 

        String authtokenType = mAuthTokenType; 
        // Creating the account on the device and setting the auth token we got 
        // (Not setting the auth token will cause another call to the server to authenticate the user) 
        mAccountManager.addAccountExplicitly(account, code, null); 
        mAccountManager.setAuthToken(account, authtokenType, authtoken); 

        Bundle data = new Bundle(); 
        data.putString(AccountManager.KEY_ACCOUNT_NAME, accountName); 
        data.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccountType); 
        data.putString(AccountManager.KEY_AUTHTOKEN, authtoken); 
        data.putString(PARAM_USER_PASS, code); 
        data.putBoolean(ARG_IS_ADDING_NEW_ACCOUNT, true); 

        final Intent res = new Intent(); 
        res.putExtras(data); 

        setAccountAuthenticatorResult(res.getExtras()); 

        Intent i = new Intent(getBaseContext(), MyEventsActivity.class); 
        startActivity(i); 
       } 
      } 
      , 
      new Response.ErrorListener() { 
       @Override 
       public void onErrorResponse(VolleyError volleyError) { 
        Log.e(TAG, volleyError.getMessage(), volleyError); 
        showMessage("Errore nell'autenticazione. Riprova piu` tardi."); 
       } 
      }); 

    requestQueue.add(jsObjRequest); 
} 

API的是驗證代碼的方法是這樣的:

public function validateCode() { 
    $code = trim(Input::get('code')); 
    $nickName = trim(Input::get('nickname')); 
    $phoneNum = trim(Input::get('mobile')); 

    if (empty($phoneNum)) 
     abort(400, 'mobile parameters not provided.'); 

    if (empty($code)) 
     abort(400, 'code parameters not provided.'); 

    if (empty($nickName)) 
     abort(400, 'nickname parameters not provided.'); 

    $validCode = Session::get('code'); 
    Log::info('code: ' . $code . " validCode: " . $validCode); 

    if($code == $validCode) { 
     Session::forget('code'); 

     // Retrieve the user by the attributes, or instantiate a new instance... 
     $user = User::firstOrCreate(['Mobile' => $phoneNum]); 

     //aggiorno i campi nickname e password col nuovo codice 
     $user->Nickname = $nickName; 
     $user->password = $code; 

     //save! 
     $user->save(); 

     //viene usata l'autenticazione di Laravel e gli serve una password 
     $token = JWTAuth::attempt(['Mobile' => $phoneNum, 'password' => $code]); 

     return response()->json($token); 
    } else { 
     //return response()->json(array('success' => false, 'error' => 'The code isn\'t correct.')); 
     abort(401, 'The code isn\'t correct.' . $validCode); 
    } 
} 

我已經測試了Chrome和Firefox REST風格的API和登錄工作。隨着應用程序沒有。事實上,問題在於Session :: get('code');在validateCode中總是返回一個空值。我檢查了用Session :: put('code',$ code)生成的會話文件;並且是正確的。但是,當調用Session :: get('code')時,Laravel會生成另一個Session文件,而且似乎不會使用前面的文件。 我在RESTful API中禁用了CSRF中間件。

出了什麼問題?

+0

不寧靜的使用會話,添加一個令牌和控制它在代碼中。 –

+0

我不明白..當我必須添加令牌時?誰生成這個令牌? – Lic

回答

3

在服務器端存儲會話是毫無意義的。 API假設爲無狀態,因此第二個完成代碼的第一個請求並將其存儲在服務器端的會話中,會話將結束,下一個請求將不記得您設置的任何內容。

如果你想保持代碼登錄和避免使用令牌,那麼你將不得不從Android應用程序發送一個唯一的代碼來標識用戶。然後在服務器端生成代碼並將其存儲在具有user_identifier和generated_code的表格中,並創建一個模型以訪問它,例如

AttemptedLogin

USER_ID | generatedCode


0001 | 87392042

0032 | 83214320

然後在此添加到saveUser

params.put("user_id", user_id); // can be the android device ID or even a unique timestamp 

最後在validateCode服務器端用以下內容替換$ validCode行:

$user_id = trim(Input::get('user_id')); 

.... 

$validCode = AttemptedLogin::where('user_id', $user_id)->first(); 

if($code == $validCode->generatedCode) { 
    $validCode->delete(); 

.... 
+0

我是這樣做的。非常感謝! – Lic