我有两组URL - 一组是REST API,第二组是 - 非常普通的网站。 我想为REST API应用不同的安全规则,以便偶尔调用REST API的用户/脚本将使用401代码(基本身份验证就可以了) - 或者只是403。
所以我想允许访问REST API:
目前我正在试图弄清楚什么配置会让春天“理解”我想要的东西。 我提出了以下配置:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http pattern="/" security="none" />
<http pattern="/static/**" security="none" />
<!-- REST API -->
<http pattern="/rest/*" use-expressions="true">
<http-basic />
<intercept-url pattern="/*" access="isAuthenticated()" />
</http>
<!-- Site -->
<http access-denied-page="/WEB-INF/views/errors/403.jsp" use-expressions="true">
<intercept-url pattern="/index.html" access="hasRole('ROLE_USER') or hasRole('ROLE_ANONYMOUS')" />
<intercept-url pattern="/login.html" access="hasRole('ROLE_USER') or hasRole('ROLE_ANONYMOUS')" />
<intercept-url pattern="/admin/*" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login login-page="/login.html"
default-target-url="/index.html"
authentication-failure-url="/login.html?error=1" />
<logout logout-url="/logout.do" logout-success-url="/index.html" />
<anonymous username="guest" granted-authority="ROLE_ANONYMOUS" />
<remember-me />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="2" authorities="ROLE_ADMIN,ROLE_USER" />
<user name="alex" password="1" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
不幸的是,不仅基本身份验证不适用于此配置,但匿名用户发出的请求没有403响应 - 使用重定向302找到的应用程序答案我想要禁止REST API URL。
我尝试为REST API添加自定义入口点:
<beans:bean id="ep403" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
<!-- REST API -->
<http pattern="/rest/*" entry-point-ref="ep403" use-expressions="true">
<intercept-url pattern="/*" access="hasRole('ROLE_USER')" />
<http-basic />
</http>
但这也不起作用。
总结我想要得到的东西:
更新
在深入了解Spring Security内部后,我找到了决定是否拒绝某些请求的代码。这是一个所谓的“访问决策选民”,基本上所有这些都适用于某些请求,如果链中的一个访问决策选民投票拒绝访问某些资源,则该请求最终被拒绝。
因此,可以通过引入以下列方式行事的特殊访问决策选举来解决原始问题:它尝试从会话中提取关联角色(如果请求中存在任何问题)并进入具有此角色的授权步骤;如果没有会话,它会尝试根据WWW-Authenticate标头中的凭据对用户进行身份验证,然后使用与给定用户关联的角色进行授权步骤。
答案 0 :(得分:3)
作为蓝色的解决方案重新发布@建议:)希望这会对某人有所帮助。
我找到了一个简单的解决方法。我只是将一个休息控制器映射到两个不同的URL集,并将每个集分配给spring security config中的不同auth处理程序:
<!-- Defines custom security policy for Stateful REST API -->
<beans:bean id="nonRedirectingAccessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl"/>
<beans:bean id="forbiddenEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
<!-- Stateful REST API -->
<http pattern="/rest/stateful/**" use-expressions="true" entry-point-ref="forbiddenEntryPoint">
<access-denied-handler ref="nonRedirectingAccessDeniedHandler"/>
<intercept-url pattern="/rest/stateful/**" access="isAuthenticated()" />
</http>
<!-- Stateless REST API -->
<http pattern="/rest/stateless/**" use-expressions="true" create-session="stateless">
<http-basic/>
<intercept-url pattern="/rest/stateless/**" access="isAuthenticated()" />
</http>
这似乎是解决该问题的好方法,因为将来您可能希望使用特定于用户或脚本用例的唯一URL来扩展“有状态”用户或“无状态”-script REST API。
在我的情况下,当UX更改需要REST API提供一些旨在实现特定UI场景的新方法时,可能会发生这种情况,而某些脚本场景可能需要添加一些URL,以支持某些客户端脚本到服务器的交互。 / p>
答案 1 :(得分:2)
您可以使用拦截器检查具有/rest/
模式的网址。
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/rest/**"/>
<bean class="com.your.class.name.Interceptor></bean>
</mvc:interceptor>
</mvc:interceptors>
为此,在XML的标题部分添加以下行,即
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
现在在Interceptor
课程中检查您需要的内容,此课程应该实现Spring HandlerInterceptor
。
public class Interceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
//do what you need to check when the request arrives
//do authentications here
//return true if success
//else false
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
}
}
答案 2 :(得分:0)
尝试将REST pattern="/rest/*"
更改为pattern="/rest/**"
,将pattern="/*"
更改为pattern="/**"
:
<http pattern="/rest/**" use-expressions="true">
<intercept-url pattern="/**" access="isAuthenticated()" />
<http-basic />
</http>