如何在Android客户端和服务器端应用程序之间安全地发送密码?

问题描述 投票:2回答:4

我当前的Android应用程序要求用户使用用户名和密码登录。

Android应用程序调用REST Web服务进行用户登录,我不想将密码作为明文传输。

如何保护用户密码以便服务器端识别/验证每个用户?

我目前正在尝试使用Jasypt库,如下所示: -

ConfigurablePasswordEncryptor passwordEncryptor = new ConfigurablePasswordEncryptor();
passwordEncryptor.setAlgorithm("SHA-1");
passwordEncryptor.setPlainDigest(true);
String encryptedPassword = passwordEncryptor.encryptPassword(userPassword);
...
if (passwordEncryptor.checkPassword(inputPassword, encryptedPassword)) {
  // correct!
} else {
  // bad login!
}

但是我的服务器端是用.NET编写的,据我所知Jasypt文档,密码加密器使用随机盐。

如何让我的服务器端代码与我发送的哈希用户密码相匹配?

我的所有web服务都有HTTPS端点,这是否保证在交换访问令牌时没有人可以“在飞行中”“看到”我的用户密码?

android .net password-hash jasypt
4个回答
1
投票

如果您使用Https(TLS),则任何拦截网络的人都无法访问您的密码。

您应该在服务器端代码中散列密码字符串,而不是在客户端中


1
投票

你必须要小心自己的所作所为。考虑实现一个通用的双因素密钥共享算法,例如TOTP。 客户端散列是一种非常罕见但非常好的做法。这当然不会阻止黑客登录到用户的帐户,但它会阻止他们获取可能重用的纯文本密码。 我建议更改电子邮件和密码是在重置密码公式下完成的,这样就需要确认电子邮件/短信。 最后,正如您所做的那样,登录发生的连接是安全的非常重要,例如https / tls。


0
投票

一个好的解决方案是避免使用传统的电子邮件/密码方法进行身份验证,并使用此处建议的OTP或一次性密码的另一个答案。

考虑用户体验:在移动设备上键入电子邮件和密码非常麻烦,烦人且笨拙。然后他们还要记住他们的密码?西方世界的普通人每天可能会使用10到15个应用程序,我们想要在他们的人力记忆库中为另一个密码征税,以便在他们乘坐地铁列车的时候笨拙地输入他们的手机?

尽管拼凑起来具有挑战性,但考虑一次性密码。有了它,用户输入电话号码作为识别令牌。

从理论上讲,每个用户都有自己独特的电话号码,用户可以轻松记住。由于您的用户在他们的Android设备上,到目前为止有道理,对吗?并没有尴尬的电子邮件和密码输入。

在他们输入他们的电话号码之后,我们然后将他们的代码发送到移动设备,这是一个4到6位数字。用户在应用程序中输入该代码,从而证明他们是电话号码所绑定的设备的所有者。

OTP优于电子邮件/密码的好处是它在用户部分需要的内存非常少。是的,它甚至比OAuth更好,因为如果用户从未通过移动浏览器登录Gmail帐户或Github帐户,该怎么办?然后他们回到移动设备的电子邮件/密码尴尬风格认证。

一次性密码是用户友好的。

但是你说没关系,但它是否安全,更重要的是问题......我怎样才能让我的服务器端代码与我发送的哈希用户密码相匹配?

是的,所以One Time Password技术始终是一个进行IMO的雄心勃勃的项目。

因此,我们需要保留用户应该输入到设备中的代码,以便我们可以在将来的某个时刻对其进行比较。当您生成代码时,请将其保存到Firebase,以便将来某个时候您可以回到Firebase并说出电话号码为212-555-1212的用户刚刚向您发送了代码1234,这是正确的代码吗?

因此,Firebase与OTP协同工作的方式是您可以将代码存储在Firebase中。然而,挑战实际上是向用户发送代码。这是一条实际的短信。要解决这个问题,你不能单独使用Firebase,你可以整合极受欢迎的Twilio。 Twilio就是通过手机短信与用户互动,因此我们可以利用Twilio向用户发送代码。

您还可以在Firebase中处理身份验证或用户系统。用户输入OTP后,我们会通过Firebase生成JSON Web令牌。

因此,所有JSON存储和反映用户身份的所有信息都可以保存在Firebase上。

但是我还没有回答这个问题的另一部分:

如何保护用户密码以便服务器端识别/验证每个用户?

好的,所以你需要比较一些服务器上的代码。它不能是Firebase,因为Firebase只是一个数据存储区,它是一个存储JSON数据的地方,它不能让我们运行自定义代码。

那么你是否编写了一个服务器来进行代码比较?我们不想在用户的设备上进行这种比较。

那么我们该怎么办?另外,我们如何生成代码?也不要使用用户的设备。

那么我们在哪里生成代码?我们知道使用Firebase数据存储来存储代码,但我们如何生成它?

这对谷歌云功能来说是一个很好的工作。

因此,Google云端功能是在Google服务器上按需运行一次的代码段。 GCF具有紧密的互操作性以及与Firebase数据存储的集成。

我们可以为Firebase内部的数据添加一些逻辑或处理。 GCF将允许您使用一些自定义逻辑来生成代码并将其保存到Firebase,GCF也可以在用户发送代码后对其进行比较。

AWS Lambda和GCF在功能上几乎完全相同,因此也可以选择。


-1
投票

在客户端(移动应用程序)和服务器之间实现身份验证和授权时,您需要考虑几件事情。首先,您的服务器有什么身份验证和授权机制来请求api端点? (它是双因素身份验证吗?它是基于承载令牌(授权类型的用户名和密码)吗?它是基于承载令牌(grant-type access-token)吗?

其次,正如您所提到的,服务器编程是基于.Net的,但您是否可以更具体地说明您的服务层(Api)是用WebApi 2还是OData编写的?

最后,您的服务器是否允许使用或不使用SSH进行通信,即HTTP与HTTPS通信?如果是使用SSH,则可以转移用户凭据,即用户名和密码,但它永远不会通过HTTP保护到转移凭证。

然后,只有它在您的结束,即在Android移动应用程序中实现根据服务器要求与api端点通信的身份验证和授权机制。

例如,我的服务器需要实现基于令牌的身份验证(bearer token和grant-type password)来使每个服务器请求(GET, POST, DELETE, PUT),并且我已经使用改进客户端实现如下:

 public Retrofit getRetrofitClient() {

    // first add the authorization header
    OkHttpClient mOkClient = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request newRequest  = chain.request().newBuilder()
                    .addHeader("Authorization", "XXXXXXXXXXXX")
                    .build();
            return chain.proceed(newRequest);
        }
    }).build();

    if (retrofit==null) {
        retrofit = new Retrofit.Builder()
                .client(mOkClient)
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
                .build();
    }
    return retrofit;
}

我的服务是

  public interface LoginService {

    @POST("/api/token")
    @FormUrlEncoded
    Call<TokenModel> getToken(@Field("username") String username,
                              @Field("password") String password,
                              @Field("grant_type") String grantType);

}

现在我可以在每个请求中使用此令牌与服务器进行通信。我不需要通过公共互联网传输用户名和密码,而是仅使用令牌,它有24小时到期(因为服务器已实现此令牌到期日期)。

希望它能帮助您了解客户端(Android移动应用程序)和服务器之间的身份验证和授权机制。

© www.soinside.com 2019 - 2024. All rights reserved.