我正在尝试为我的Spring安全性受保护的servlet实现一个AccessDecisionManager
,并且需要检查“Authorization”标头的内容。我有以下代码,但是标头(我确定100%确定发送了该标头)正在返回null
:
public class MyAccessDecisionManager implements AccessDecisionManager {
public void decide(Authentication arg0, Object arg1, Collection<ConfigAttribute> arg2) throws AccessDeniedException, InsufficientAuthenticationException {
HttpServletRequest req = ((FilterInvocation) arg1).getHttpRequest();
String authHeader = req.getHeader("Authorization"); //this is null
//Do stuff
}
}
在调试器中查看
req
,我可以深入研究有趣的外观,以查看以下结构:SecurityContextHolderAwareRequestWrapper req
|-SavedRequestAwareWrapper request
|-DefaultSavedRequest savedRequest
|-TreeMap headers
|-HttpSessionSecurityContextRepository$Servlet3SaveToSessionRequestWrapper request
|-RequestWrapper request
|-RequestFacade request
|-Request request
|-Request coyoteRequest
|-MimeHeaders headers
MimeHeaders headers
包含我的“Authorization”标头,并且具有正确的值,因此我知道标头正将其发送到我的服务器。但是,TreeMap headers
缺少我的Authorization标头,并且(我假设)是getHeaders()
正在查看的内容。我尝试在客户端添加“foo”标头以检查问题是否专门与“Authorization”有关,但我看到的是完全相同的行为。我只能访问的标头是“accept-encoding”,“connection”,“host”和“user-agent”。
配置为:
<bean id="myAccessDecisionManager" class="com.example.MyAccessDecisionManager" />
<security:http pattern="/api/**"
access-decision-manager-ref="myAccessDecisionManager"
entry-point-ref="myAccessDeniedHandler">
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:anonymous enabled="true"/>
<security:access-denied-handler ref="myAccessDeniedHandler"/>
</security:http>
谁能解释这是怎么回事或标题为何丢失?有什么方法可以访问
decide()
函数中的值? (或者是否有更好的方法可以根据标头值做出决定?) 最佳答案
我无法确定AccessDecisionManager
中的问题是什么或如何获得对其他请求标头的访问。相反,我通过在api路径上禁用Spring Security来解决此问题:
<security:http pattern="/api/**" security="none"/>
...并使用Spring MVC拦截器代替:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/api/**"/>
<bean class="com.example.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
我必须将我的
AccessDecisionManager
和AuthenticationEntryPoint
的逻辑都包含在拦截器的preHandle()
方法中,这并不理想,但可以工作。