如何使用 Spring 安全性保护包含的页面

Posted

技术标签:

【中文标题】如何使用 Spring 安全性保护包含的页面【英文标题】:How to secure an included page with Spring security 【发布时间】:2014-11-24 18:44:16 【问题描述】:

假设我有一个包含另一个受保护页面的 main.jsp

<%
RequestDispatcher rd = request.getRequestDispatcher("secure/protected.jsp");
rd.include(request, response);
%>


<http auto-config="true" once-per-request="true">
        <intercept-url pattern="/secure/**" access="ROLE_SUPERVISOR" />
....
</http>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

目前,我发现的是:

实际调用了 Spring 安全过滤器。 protected.jsp 仍显示在 main.jsp 中。 (但我希望 protected.jsp 会被 spring security 阻止)

我已阅读相关讨论: Spring Security Allows Unauthorized User Access to Restricted URL from a Forward

是否可以保护包含的 jsp?如果不是,为什么? 我猜原因是当我们使用请求调度器时,我们仍然传递原始请求,所以spring安全过滤器只知道原始请求路径(main.jsp),不知道目标包含路径(protectected.jsp)。因此,它不会阻止包含 protectedected.jsp

但它不起作用。 我使用 Spring 安全 3.1.2。

【问题讨论】:

once-per-request 必须设置为 false @PavelHoral 谢谢。试过了,还是不行。 【参考方案1】:

包含一个 JSP 基本上意味着将另一个 JSP 的内容内联到当前输出 (html) 文档中。 正如 san-krish 提到的,这些 JSP 包括不进行 servlet 过滤操作。

它们的主要目的是在您拥有可重用 JSP 时使用,例如导航或分页。 通常,它们不会被 servlet 容器公开。因此,他们应该生活在WEB-INF 之下。

您没有披露有关您的申请的足够信息。但您似乎正试图在一个 JSP 中路由到不同的页面。

将其视为设计缺陷。您的视图(JSP)应该只渲染模型数据,而您的控制器(HttpServlet 甚至更好的Spring MVC 请求处理程序)应该决定是否应该使用 JSP A 或 B 进行渲染。

如果我的假设有误 - 抱歉打扰了。

如果您尝试在登录后向用户显示不同的内容,您应该考虑实现自定义 AuthenticationSuccessHandler,它根据附加到 principal 的角色重定向到不同的 JSP。

如果您只想根据用户角色显示或隐藏页面内容,则应利用Spring Security's Taglib

在您的 pom.xml 中包含 Spring Security Taglib 工件(我认为 Maven 是理所当然的)。

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>3.1.1.RELEASE</version>
</dependency>

将 taglib 添加到您的 JSP。

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>

并用authorize 标签包围include。更好的是,您应该将 authorize 移动到 protected.jsp 以获得更好的可重用性。

<security:authorize ifAllGranted="ROLE_SUPERVISOR">
    <jsp:include page="secure/protected.jsp" />
</security:authorize>

【讨论】:

谢谢。我同意从用例的角度来看,包含受保护的页面可能有点奇怪。 Spring的授权标签也是我找到的合适的解决方案。【参考方案2】:

当您include main.jsp 中的jsp 页面时,它不会进行servlet 过滤操作。换句话说,它不会到达服务器,而是编译并放置在您的主页中。

spring security 的概念基于ServletFilter,因为您包含的页面不会被 spring security 拦截,它不会阻止其访问。

希望这会有所帮助!!

【讨论】:

以上是关于如何使用 Spring 安全性保护包含的页面的主要内容,如果未能解决你的问题,请参考以下文章

CAS服务器认证成功后,如何使Spring安全将用户重定向到原始请求的页面

Spring security - 允许导航但保护某些页面

使 Spring 安全会话无效

使用受 Spring 安全性保护的资源创建简单 Web 应用程序

如何使用 Spring Boot 保护单页应用程序

如何使用 Spring Security 注入默认安全标头