从Android应用程序登录到Silex REST API



我使用Silex在PHP中开发了一个API,我希望能够从Android应用程序和网站访问它。我已经开发了网站,谁能够完美地访问API。

我试图对我的Android应用程序做同样的事情,但它不起作用。我遇到的问题是我真的不明白如何使用与网站相同的方法将自己登录为用户。我使用Silex的安全服务提供商来处理登录和令牌部分,这在我的网站上工作。

以下是代码:

应用程序中的安全服务提供商.php :

$app->register(new SilexProviderSecurityServiceProvider(), array(
'security.firewalls' => array(
'login' => array(
'pattern' => '^/login$',
),
'secured' => array(
'pattern' => '^/',
'form' => array('login_path' => '/login', 'check_path' => '/login_check'),
'logout' => array('logout_path' => '/logout'),
'users' => function($app) {
return new AppUserProviderUserProvider($app['db']);
}),
),

'security.role_hierarchy' => array(
'ROLE_USER' => array(),
'ROLE_ADMIN' => array('ROLE_USER'),
),
'security.access_rules' => array(
array('^/user', 'ROLE_USER'),
array('^/admin', 'ROLE_ADMIN'),
)
));

登录部分在 login.html.twig 调用中使用/login:

<form class="form-horizontal" role="form" method="post" action="{{ path('login_check') }}">
<div class="form-group">
<label for="inputEmail1" class="col-lg-2 col-sm-2 control-label">Login</label>
<div class="col-lg-10">
<input type="text" class="form-control" id="login" name="_username" placeholder="Login">
</div>
</div>
<div class="form-group">
<label for="inputPassword1" class="col-lg-2 col-sm-2 control-label">Mot de Passe</label>
<div class="col-lg-10">
<input type="password" class="form-control" id="mdp" name="_password" placeholder="Mot de Passe">
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<div class="checkbox">
<label>
<input type="checkbox"> Se Souvenir de Moi
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button type="submit" class="btn btn-danger">Connexion</button>
</div>
</div>
</form>

登录安卓中的活动:

public class LoginActivity extends AppCompatActivity {
private static final String TAG = "LoginActivity";
private static final int REQUEST_SIGNUP = 0;
@Bind(R.id._username) EditText username;
@Bind(R.id._password) EditText password;
@Bind(R.id.btn_login) Button _loginButton;
@Bind(R.id.link_signup) TextView _signupLink;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
_loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
login();
}
});
_signupLink.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Start the Signup activity
Intent intent = new Intent(getApplicationContext(), SignupActivity.class);
startActivityForResult(intent, REQUEST_SIGNUP);
finish();
overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
}
});
}
public void login() {
if (!validate()) {
onLoginFailed();
return;
}
_loginButton.setEnabled(false);
final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this,
R.style.AppTheme_Dark_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Authenticating...");
progressDialog.show();
String _username = username.getText().toString();
String _password = password.getText().toString();
Call<User> userCall = APIClient.getApiInterface().getUser(_username, _password);
userCall.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
if (response.body() == null) {
// Toast
} else
{
}
}
@Override
public void onFailure(Call<User> call, Throwable t) {
Log.d("Going here", "Don't know why");
}
});
// TODO: Implement your own authentication logic here.
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
// On complete call either onLoginSuccess or onLoginFailed
onLoginSuccess();
// onLoginFailed();
progressDialog.dismiss();
}
}, 3000);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_SIGNUP) {
if (resultCode == RESULT_OK) {
// TODO: Implement successful signup logic here
// By default we just finish the Activity and log them in automatically
this.finish();
}
}
}
@Override
public void onBackPressed() {
// Disable going back to the MainActivity
moveTaskToBack(true);
}
public void onLoginSuccess() {
_loginButton.setEnabled(true);
finish();
}
public void onLoginFailed() {
Toast.makeText(getBaseContext(), "Login failed", Toast.LENGTH_LONG).show();
_loginButton.setEnabled(true);
}
public boolean validate() {
boolean valid = true;
String _username = username.getText().toString();
String _password = password.getText().toString();
if (_username.isEmpty()) {
username.setError("enter a valid email address");
Log.d(TAG, "Login");
valid = false;
} else {
username.setError(null);
}
if (_password.isEmpty() || _password.length() < 4) {
password.setError("between 4 and 10 alphanumeric characters");
valid = false;
} else {
password.setError(null);
}
return valid;
}
}

APIClient in Android :

public class APIClient {
public static final String BASE_URL = "http://localhost:8080/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
public static APIInterface getApiInterface() {
APIInterface apiService = APIClient.getClient().create(APIInterface.class);
return apiService;
}

}

Android 中的 APIInterface :

public interface APIInterface {
@FormUrlEncoded
@POST("login")
Call<User> getUser(@Field("_username") String _username, @Field("_password") String _password);
}

所以从技术上讲,我认为发送带有字段"_username"和"_password"的表单可以做到这一点,但显然它没有。

自从我开始在所有移动/网络服务/网络环境中学习和工作以来,已经有几个月了,所以我对所有内容都不是很熟悉。如果您需要有关代码的更多信息,或者是否有更好的方法,也请告诉我。

嗨,我想你正在寻找Silex guard_authentication

假设您有一个 API,您的客户端将在其中为每个请求发送一个 X-AUTH-TOKEN 标头。此令牌由用户名后跟密码组成,用冒号分隔(例如 X-AUTH-TOKEN: coolguy:awesomepassword)。您的工作是阅读此内容,找到关联的用户(如果有)并检查密码。

*更新:

检查这个: https://stackoverflow.com/a/21600804/4270737

https://silex.sensiolabs.org/index.php/doc/2.0/cookbook/guard_authentication.html

最新更新