Spring Security 认证 RESTful Web 服务
Posted
技术标签:
【中文标题】Spring Security 认证 RESTful Web 服务【英文标题】:Spring Security authenticating RESTful web service 【发布时间】:2012-11-06 07:24:57 【问题描述】:我正在为我的 RESTful Web 服务(使用 Spring MVC 实现)添加基本身份验证,而 Spring Security 以前从未真正使用过它。现在我只是使用内存中的UserService
,目的是稍后添加一个基于存储库的。
<security:http>
<security:http-basic />
<security:intercept-url pattern="/**" access="ROLE_ADMIN" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="admin" password="admin"
authorities="ROLE_USER, ROLE_ADMIN" />
<security:user name="guest" password="guest"
authorities="ROLE_GUEST" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
这很好用,即发送以下请求授予我访问所需资源的权限(其中编码字符串为 admin:admin):
GET /user/v1/Tyler HTTP/1.1
Authorization: Basic YWRtaW46YWRtaW4=
发送以下请求会给我一个错误 403(其中编码的字符串是 guest:guest):
GET /user/v1/Tyler HTTP/1.1
Authorization: Basic Z3Vlc3Q6Z3Vlc3Q=
但是,如果提供的用户名不包含在UserService
中,则发送请求不会导致错误 403,如我所料(或至少是所希望的),而是继续提示输入用户名和密码。例如。 (其中编码的字符串是用户:用户):
GET /user/v1/Tyler HTTP/1.1
Authorization: Basic dXNlcjp1c2Vy
当提供无法识别的用户凭据时,是否需要额外配置才能响应错误 403?我该怎么做呢?
【问题讨论】:
【参考方案1】:首先,
403 Forbidden
应在用户已通过身份验证但无权执行特定操作时使用。在您的示例中,guest
已成功通过身份验证,但未被授予查看页面的权限,因为他只是一个访客。
您应该使用401 Unauthorized
表示您的用户未成功通过身份验证。
更多关于 HTTP 错误代码:http://en.wikipedia.org/wiki/HTTP_401#4xx_Client_Error
其次,
您可以通过扩展BasicAuthenticationFilter
来指定您的自定义行为。
有 protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse AuthenticationException failed)
方法,您可以覆盖并执行任何适当的操作。在默认实现中,该方法为空。
关于注入自定义过滤器的 Spring Security 文档:CLICK
编辑:
每次验证输入无效时 Spring Security 会做什么:
public class BasicAuthenticationEntryPoint implements AuthenticationEntryPoint
...
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException
response.addHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\"");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
所以,默认行为是正确的。用户被发送 401 并被要求提供有效的登录名/凭据。
在覆盖之前,请尝试了解默认行为。源码:CLICK
【讨论】:
谢谢,Maciej。你是对的,这毕竟是正确的行为。很高兴知道如何注入自定义过滤器。【参考方案2】:您应该在 wget 或 curl 等客户端中尝试此操作。如果您被 401 拒绝,您的浏览器会多次为 Basic redentials 唠叨。这可能就是这种情况。
【讨论】:
我正在使用 Mac OSX 的 HTTP 客户端(类似于 Windows 的 Fiddler)。我假设因为它明确地为一种情况给出了 403,所以它会为另一种情况做同样的事情。以上是关于Spring Security 认证 RESTful Web 服务的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot + Spring Security自定义用户认证
Spring Security Authentication (认证)