Android|使用 retrofit2 和本地 API 的基本身份验证
Android| Basic Auth using retrofit2 and local API
我开始制作一个应用程序并将其连接到模拟 API。现在我想将它连接到我的 PC 上运行的 API。
首先,我正在尝试实现登录访问。由于我的 API 的基础 URL 是 http://localhost:5000/energy/api/ 我将其更改为 http://<< MyIPAddress >>:5000/energy/api/ (不知道这是否是正确的)。我正在我的实际 phone 上测试它。
但是我的代码用户名和密码作为参数传递,而我想使用基本身份验证登录(这就是我在 Postman 中的做法)。
例如,这就是我希望完成身份验证的方式:
但是我的代码得到了这个:
这是我的请求管理器:
object RequestManager {
val interceptor = HttpLoggingInterceptor()
val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
init {
interceptor.level = HttpLoggingInterceptor.Level.BODY
}
val retrofit = Retrofit.Builder()
.baseUrl("http://<<MYIP>>:5000/energy/api/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
val service = retrofit.create(Api::class.java)
我的MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
login_button.setOnClickListener {
buttonClicked()
}
if (getTokenFromPrefs()?.length!! > 0) {
openSearchActivity()
}
}
private fun buttonClicked() {
val username = username_edittext.text.toString()
val password = password_edittext.text.toString()
Log.d("eeee","button clicked " + username_edittext.text.toString() + " password "+password_edittext.text.toString() )
val call = RequestManager.service.login(username, password)
call.enqueue(object : Callback<LoginResponse> {
override fun onResponse(call: Call<LoginResponse>, response: Response<LoginResponse>) {
if (response.isSuccessful ){
openSearchActivity()
saveTokenToPrefs(response.toString())
}else {
}
}
override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
}
})
}
val TOKENPREFSKEY = "tokenprefskey"
private fun saveTokenToPrefs(token: String) {
val pref = applicationContext.getSharedPreferences("CGEEnergy", 0)
val editor = pref.edit()
editor.putString(TOKENPREFSKEY, token)
editor.commit()
}
private fun getTokenFromPrefs(): String? {
val pref = applicationContext.getSharedPreferences("CGEEnergy", 0)
return pref.getString(TOKENPREFSKEY, "")
}
private fun openSearchActivity() {
val intent = Intent(this, SearchActivity::class.java)
startActivity(intent)
if (getTokenFromPrefs()?.length!! == 0) {
openMainActivity()
}
finish()
}
private fun openMainActivity() {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}
}
我的 API.kt 代码:(由用户 Hello World 编辑和更正)
interface Api {
@POST("Login")
@FormUrlEncoded
fun login(@Field("username") username: String, @Field("password") password: String): Call<LoginResponse>
}
我的LoginResponse.java代码:
public class LoginResponse {
@SerializedName("token")
@Expose
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
有人可以帮助我进行基本身份验证吗?
是不是我的基地URL也有问题? (添加 IP 而不是本地主机)。
任何提示将不胜感激。
PS。对于 http 安全问题,我已经添加了
android:usesCleartextTraffic="true"
在我的AndroidManifest.xml
@Query
此注释用于 'GET' 方法。
您需要在 'POST' 方法的函数名前添加 @FormUrlEncoded
。并且您还需要使用 @Field
而不是 @Query
for 'POST' 方法。所以你的 API Call initerface 方法会变成这样。
@POST("Login")
@FormUrlEncoded
fun login(@Field("username") username: String, @Field("password") password: String): Call<LoginResponse>
基本身份验证需要以下格式的授权 header:
"Basic " + Base64.encode(<username>:<password>)
您应该像这样更改 Api 界面
interface Api {
@POST("Login")
fun login(@Header("Authorization") authorization: String): Call<LoginResponse>
}
现在您可以像这样向调用添加 Auth header:
val authPayload = "$userId:$password"
val data = authPayload.toByteArray()
val base64 = Base64.encodeToString(data, Base64.NO_WRAP)
val call = RequestManager.service.login("Basic $base64".trim())
我开始制作一个应用程序并将其连接到模拟 API。现在我想将它连接到我的 PC 上运行的 API。
首先,我正在尝试实现登录访问。由于我的 API 的基础 URL 是 http://localhost:5000/energy/api/ 我将其更改为 http://<< MyIPAddress >>:5000/energy/api/ (不知道这是否是正确的)。我正在我的实际 phone 上测试它。
但是我的代码用户名和密码作为参数传递,而我想使用基本身份验证登录(这就是我在 Postman 中的做法)。
例如,这就是我希望完成身份验证的方式:
但是我的代码得到了这个:
这是我的请求管理器:
object RequestManager {
val interceptor = HttpLoggingInterceptor()
val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
init {
interceptor.level = HttpLoggingInterceptor.Level.BODY
}
val retrofit = Retrofit.Builder()
.baseUrl("http://<<MYIP>>:5000/energy/api/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
val service = retrofit.create(Api::class.java)
我的MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
login_button.setOnClickListener {
buttonClicked()
}
if (getTokenFromPrefs()?.length!! > 0) {
openSearchActivity()
}
}
private fun buttonClicked() {
val username = username_edittext.text.toString()
val password = password_edittext.text.toString()
Log.d("eeee","button clicked " + username_edittext.text.toString() + " password "+password_edittext.text.toString() )
val call = RequestManager.service.login(username, password)
call.enqueue(object : Callback<LoginResponse> {
override fun onResponse(call: Call<LoginResponse>, response: Response<LoginResponse>) {
if (response.isSuccessful ){
openSearchActivity()
saveTokenToPrefs(response.toString())
}else {
}
}
override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
}
})
}
val TOKENPREFSKEY = "tokenprefskey"
private fun saveTokenToPrefs(token: String) {
val pref = applicationContext.getSharedPreferences("CGEEnergy", 0)
val editor = pref.edit()
editor.putString(TOKENPREFSKEY, token)
editor.commit()
}
private fun getTokenFromPrefs(): String? {
val pref = applicationContext.getSharedPreferences("CGEEnergy", 0)
return pref.getString(TOKENPREFSKEY, "")
}
private fun openSearchActivity() {
val intent = Intent(this, SearchActivity::class.java)
startActivity(intent)
if (getTokenFromPrefs()?.length!! == 0) {
openMainActivity()
}
finish()
}
private fun openMainActivity() {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}
}
我的 API.kt 代码:(由用户 Hello World 编辑和更正)
interface Api {
@POST("Login")
@FormUrlEncoded
fun login(@Field("username") username: String, @Field("password") password: String): Call<LoginResponse>
}
我的LoginResponse.java代码:
public class LoginResponse {
@SerializedName("token")
@Expose
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
有人可以帮助我进行基本身份验证吗? 是不是我的基地URL也有问题? (添加 IP 而不是本地主机)。 任何提示将不胜感激。
PS。对于 http 安全问题,我已经添加了
android:usesCleartextTraffic="true"
在我的AndroidManifest.xml
@Query
此注释用于 'GET' 方法。
您需要在 'POST' 方法的函数名前添加 @FormUrlEncoded
。并且您还需要使用 @Field
而不是 @Query
for 'POST' 方法。所以你的 API Call initerface 方法会变成这样。
@POST("Login")
@FormUrlEncoded
fun login(@Field("username") username: String, @Field("password") password: String): Call<LoginResponse>
基本身份验证需要以下格式的授权 header:
"Basic " + Base64.encode(<username>:<password>)
您应该像这样更改 Api 界面
interface Api {
@POST("Login")
fun login(@Header("Authorization") authorization: String): Call<LoginResponse>
}
现在您可以像这样向调用添加 Auth header:
val authPayload = "$userId:$password"
val data = authPayload.toByteArray()
val base64 = Base64.encodeToString(data, Base64.NO_WRAP)
val call = RequestManager.service.login("Basic $base64".trim())