从 Android 调用使​​用 Spring Security 保护的 REST Web 服务

Posted

技术标签:

【中文标题】从 Android 调用使​​用 Spring Security 保护的 REST Web 服务【英文标题】:Calling a REST web service secured with Spring Security from Android 【发布时间】:2011-06-07 13:19:26 【问题描述】:

我使用 Spring Security 在 Grails 应用程序中托管 REST Web 服务,即:

@Secured(['IS_AUTHENTICATED_REMEMBERED'])
def save = 
    println "Save Ride REST WebMethod called"

我从 android 应用程序调用它。 (调用不安全的服务就可以了。)

为了调用该服务,我手动构建了一个请求 (HttpUriRequest) 并使用 HttpClient 执行它。

我想知道最佳实践是什么,以及如何实施它们...具体来说,我应该:

    执行一次登录,检索 JSESSION_ID,然后将包含它的标头添加到每个后续请求的 HttpUriRequest 中? 或者(我什至不知道该怎么做)在每个请求中直接包含登录名和密码,在 cookie/服务器端会话之前

我想我可以让选项 1 工作,但不确定 Spring Security 是否允许 (2),如果这是要走的路...谢谢!

--而且,没有任何我想念的图书馆可以为我做这一切,是吗? :)

【问题讨论】:

【参考方案1】:

Spring security确实支持基本身份验证和基于表单的身份验证(在 URL 中嵌入用户名/密码)。

REST 服务通常针对每个请求进行身份验证,而不是通常通过会话进行身份验证。默认的 spring 安全认证(假设你在 3.x 上)应该寻找基本的认证参数或表单参数(j_username 和 j_password)(形式为http://you.com/rest_service?j_username=xyz&j_password=abc)。

手动将 j_username/j_password 添加到 URL 上,将它们添加为 post 参数(我相信),或设置基本身份验证用户名/密码应该都可以针对默认 Spring Security 拦截器对 REST 服务进行身份验证,就在盒子。

我承认我没有在 REST 服务上尝试过这个,虽然我清楚地记得在文档中阅读过这个,就像我最近对 ​​spring security 的基本页面登录所做的一样。免责声明结束。

【讨论】:

非常感谢您的回答,这很接近(这些想法很有帮助)但没有开箱即用 - 我发了一篇关于如何让它工作的帖子:@987654322 @ 那是一篇很棒的帖子,感谢您的贡献,我相信它会被发现并对许多其他人有用。 将用户名和密码放在 URL 中通常被认为是个坏主意。 Web 服务器日志文件通常包含会暴露您的凭据的查询参数。任何从浏览器访问您的 RESTful 服务的人都会在他们的历史记录中公开凭据。【参考方案2】:

我认为您可以使用类似于 oauth 工作方式的 login-once-and-get-a-token 方法。

在安全通道 (https/ssl) 之外通过网络发送用户名和密码是一个糟糕的主意。网络上的任何人都可以嗅探您的请求包并查看明文密码。

另一方面,如果您使用令牌方法,由于令牌字符串是随机生成的,即使令牌被泄露,最坏的情况是有人可以使用令牌访问您的 REST API。

另一种解决方案是通过 ssl 隧道 (HTTPS)。我实际上做了一个比较,结果显示:80 requests/min(https) vs 300 requests/min(http)

【讨论】:

以上是关于从 Android 调用使​​用 Spring Security 保护的 REST Web 服务的主要内容,如果未能解决你的问题,请参考以下文章

Android 如何使edittext默认失去焦点

使 Spring 安全会话无效

spring:利用Spring AOP 使日志输入与方法分离

android中用Camera来调用摄像头,只能用takePicture来拍照吗?

从android应用程序验证spring boot应用程序(使用jwt)

使用 Spring 从控制器层调用存储库和服务