Rest API public always call login


(jose.maia) #1

I don´t understand why a simple rest api can be a lot of problem and lost of time, ohh my Goodm there is someone can helpme ?

0- We have using the advanced mode Yii

1- We have a system im Yii2, it is use autentication and autorization, but now, i need to create a rest api for a cliente android. I need disable the autentication and autorization for all methods this api, because i just need to get the username and name of the user to put it in alog table.

2- The is my problema, i can´t be able to disable the login and the autentication fo do it, when i am not loged in this sistemy. When a do the logout, get a forbidem 403 and whem call the url on android i get the html of the login Yii.

3- I tryed a lot of tecniques to do it, but no sucsess, below, the is my files.

My controller:

class TokenController extends \yii\rest\ActiveController
{
public $modelClass = Token::class;
}

API module definition:

class ApiExpedicao extends \yii\base\Module
{
/**
* {@inheritdoc}
*/
public $controllerNamespace = ‘app\modules\api\controllers’;

/**
 * {@inheritdoc}
 */
public function init()
{
    parent::init();
    \Yii::$app->user->enableSession = false;
    // custom initialization code goes here
}

}

My Module:

class Module extends \yii\base\Module
{
public $controllerNamespace = ‘app\modules\v1\controllers’;

public function init()
{
    parent::init();
    \Yii::$app->user->enableSession = false;
}

}

My Main.php config in backend

‘user’ => [
//‘enableSession’ => false,//resolvido a diferenca no mofule
‘loginUrl’ => null,//parece nao afetar a aplocacao
‘identityClass’ => ‘common\models\User’,
‘enableAutoLogin’ => true,
‘identityCookie’ => [‘name’ => ‘_identity-backend’, ‘httpOnly’ => true],

    ],

My Main.php in common config

‘authManager’ => [
‘class’ => ‘yii\rbac\DbManager’,
],
‘urlManager’ => [
‘enablePrettyUrl’ => true,
‘enableStrictParsing’ => false,//no equals
‘showScriptName’ => true,//no equals
‘rules’ => [

            ['class' => 'yii\rest\UrlRule','pluralize' => false, 'controller' => ['v1/api'], 'except' => ['delete', 'create', 'update']],
            ['class' => 'yii\rest\UrlRule','pluralize' => false, 'controller' => ['v1/token']],
        ],
    ],

'modules' => [
    'v1' => [
        'basePath' => '@app/modules/v1',
        'class' => 'app\modules\v1\Module',
    ],
],

];

My Entity from database to test

class Token extends ActiveRecord
{

public static function collectionName()
{
    return 'token';
}

public function attributes()
{
    return ['id', 'value'];
}

public function behaviors()
{
    return [
        TimestampBehavior::className(),		// Auto timestamp created and updated properties
    ];
}


public function rules()
{
    return [
        [['value'], 'string'],
        
    ];
}


public function fields()
{
    return [
        'id',
        'value',
    ];
}

}

the log tha i receved when i am not loged

2019-10-01 10:18:04 [192.168.5.78][-][8k12d17bjm3kbfpeit8jnm3e16][error][yii\web\HttpException:403] exception ‘yii\web\ForbiddenHttpException’ with message ‘Login Required’ in /var/www/html/azulejo_yii_dev/vendor/yiisoft/yii2/web/User.php:454

The url caled on the browser when i am loged:

http://host/index.php/v1/token

The response of the request:

<?xml version="1.0" encoding="ISO-8859-1"?> 1 teste 1 2 teste 2

The response when I am not loget in the sistem or called by postman

Forbidden (#403)

Login Required

the log: 2019-10-01 10:18:04 [ip][-][8k12d17bjm3kbfpeit8jnm3e16][error][yii\web\HttpException:403] exception ‘yii\web\ForbiddenHttpException’ with message ‘Login Required’ in /var/www/html/azulejo_yii_dev/vendor/yiisoft/yii2/web/User.php:454


(jose.maia) #2

Hi friends

Now, I can do it functioned, if you are intersted, the is the answer.
My controller is

class TokenController extends \yii\rest\ActiveController
{
public $modelClass = User::class;

/**
 autentication by username and password
 */
public function actionValid(){
    $authHeader = Yii::$app->request->getHeaders()->get('Authorization');
    //echo '<pre>' ; print_r('teste: '.Yii::$app->user->identity->auth_key." - ".$authHeader);
    //die;

    $id = "id:".Yii::$app->user->identity->id;
    $name = "name:".Yii::$app->user->identity->name;
    $RA_MAT = "RA_MAT:".Yii::$app->user->identity->RA_MAT;

    $result = $id."-".$name."-".$RA_MAT;
    //return json_encode(Yii::$app->user->identity->getAttributes(array('id','name','RA_MAT')));
    return $result;
}

public function behaviors()
{
    //pega os parametros da url
    $param = Yii::$app->request->getQueryParams();
    $username = $param['username'];
    $password = $param['password'];

    $behaviors = parent::behaviors();

    $behaviors['authenticator'] = [
        'class' => HttpBasicAuth::className(),
        'auth' => function ($username, $password) {
            $user = User::findByUsername($username);

            if ($user && $user->validatePassword($username, $password)) {
                return $user;
            }else{
                return $user;
            }
        }
    ];
    //here i put the user in the session of the Yii user
    Yii::$app->user->login(User::findByUsername($username),  3600 * 24 * 30);
    return $behaviors;
}

}

the url to do in the postman
http://host/index.php/v1/token/test?username=jose&password=123456

int the android

the cal
ServiceRestExpedicao service = new ServiceRestExpedicao(LoginActivity.this, username, password);
String response = service.execute().get();

the service android class

public class ServiceRestExpedicao extends AsyncTask<String, Void, String>{

private static String stringURL = null;
private  URL url = null;
private Context context;
private Map<String, List<String>> headerFields;
private String username;
private String password;

public ServiceRestExpedicao(String stringURL, Context context){
    this.stringURL = stringURL;
    this.context = context;
}

public ServiceRestExpedicao(URL url, Context context){
    this.url = url;
    this.context = context;
}

public ServiceRestExpedicao(Context context){
    this.context = context;
}

public ServiceRestExpedicao(Context context, String username, String password){
    this.context = context;
    this.username = username;
    this.password = password;
}

//@Override
private String conectar() {

    StringBuilder response = new StringBuilder();

    try {
       

        url = new URL("http://host/index.php/v1/token/valid?username=" + username + "&password=" + password);
        String encoding = Base64Encoder.encode(username + ":" + password);

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Authorization", "Basic " + encoding);
        //connection.setRequestProperty("Content-type", "application/json");
        connection.setRequestProperty("Accept", "application/json");
        //connection.setRequestProperty("Content-Type", "text/plain");
        connection.setDoOutput(true);
        connection.setConnectTimeout(5000);
        connection.connect();

        InputStream content = (InputStream) connection.getInputStream();
        headerFields = connection.getHeaderFields();
        BufferedReader in = new BufferedReader(new InputStreamReader(content));

        String line;
        while ((line = in.readLine()) != null) {
            response.append(line);
        }

        System.out.println("-------------------TESTE service: "+ response.toString());

        //System.setProperty("http.proxyHost", "my.proxyhost.com");
        //System.setProperty("http.proxyPort", "1234");

    } catch (Exception e) {
        e.printStackTrace();
        response.append(Constantes.ERRO);
    }
    return response.toString();
}

@Override
protected String doInBackground(String... params) {
    return conectar();
}

}


(Chrisb) #3

I would be careful of the security implications off sending a password in a get parameter especially on every API request.

I would suggest that you look into JWT as an authentication method.