@Secured 在控制器中不起作用,但拦截 url 似乎工作正常

发布于 2024-11-19 08:19:11 字数 2985 浏览 1 评论 0原文

看起来我的 @Controller 中的方法上的 @Secured 没有被读取。当使用基于 sec:intercept-url 的安全过滤时,这似乎工作得很好。以下代码导致 Spring Security 给我这个日志条目:

调试:org.springframework.security.web.access.intercept.FilterSecurityInterceptor - 公共对象 - 未尝试身份验证

web.xml

上下文配置位置 /WEB-INF/spring/root-context.xml

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Processes application requests -->
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/appServlet/servlet-context.xml
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- Filter security -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

servlet-context.xml 保存 viewResolvers 的配置和所有编组。此配置是注释驱动的。

root-context.xml

    <sec:global-method-security secured-annotations="enabled" />

<sec:http auto-config="true">
    <sec:http-basic/>
</sec:http>

<!-- Declare an authentication-manager to use a custom userDetailsService -->
<sec:authentication-manager>
    <sec:authentication-provider
        user-service-ref="userDetailsService">
        <sec:password-encoder ref="passwordEncoder" />
    </sec:authentication-provider>
</sec:authentication-manager>

<bean
    class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder"
    id="passwordEncoder" />
<sec:user-service id="userDetailsService">
    <sec:user name="john" password="john" authorities="ROLE_USER, ROLE_ADMIN" />
    <sec:user name="jane" password="jane" authorities="ROLE_USER" />
</sec:user-service>

PingController.java

@Controller
public class PingController {

    @Secured("ROLE_ADMIN")
    @RequestMapping(value = "/ping", method = RequestMethod.GET)
    public void ping() {
    }

}

这似乎与我使用的身份验证方法没有任何关系,因此可以忽略 basic-http-tag 。

我有这样的想法,@Secured 不起作用,因为它在另一个上下文中使用,而不是在配置安全性的 root-context.xml 中。我尝试将此配置移至 servlet-context.xml,但它似乎没有到达 springSecurityFilterChain。对这个问题和我的理论有什么想法吗?

It doesn't look like @Secured on methods in my @Controller are being read. When security filtering based on sec:intercept-url is being used, this seems to be working just fine. The following code results in Spring Security giving me this log entry:

DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Public object - authentication not attempted

web.xml

contextConfigLocation

/WEB-INF/spring/root-context.xml

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Processes application requests -->
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/appServlet/servlet-context.xml
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- Filter security -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

servlet-context.xml holds the configuration of the viewResolvers and all the marshalling. This configuration is annotation-driven.

root-context.xml

    <sec:global-method-security secured-annotations="enabled" />

<sec:http auto-config="true">
    <sec:http-basic/>
</sec:http>

<!-- Declare an authentication-manager to use a custom userDetailsService -->
<sec:authentication-manager>
    <sec:authentication-provider
        user-service-ref="userDetailsService">
        <sec:password-encoder ref="passwordEncoder" />
    </sec:authentication-provider>
</sec:authentication-manager>

<bean
    class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder"
    id="passwordEncoder" />
<sec:user-service id="userDetailsService">
    <sec:user name="john" password="john" authorities="ROLE_USER, ROLE_ADMIN" />
    <sec:user name="jane" password="jane" authorities="ROLE_USER" />
</sec:user-service>

PingController.java

@Controller
public class PingController {

    @Secured("ROLE_ADMIN")
    @RequestMapping(value = "/ping", method = RequestMethod.GET)
    public void ping() {
    }

}

This doesn't seem to have any relation to which authentication method I'm using, so the basic-http-tag can be overlooked.

I have this idea that the @Secured doesn't work because of it being used in another context than the root-context.xml in which the security is being configured. I've tried to move this configuration to the servlet-context.xml, but it doesn't seem to reach the springSecurityFilterChain. Any thoughts on the problem and and my theory?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜味超标? 2024-11-26 08:19:11

你是对的, 是在每个上下文的基础上应用的。但是,您不需要将整个安全配置移至 servlet-context.xml,只需向其中添加 元素即可。

You are right, <global-method-security> is applied at per-context basis. However, you don't need to move the whole security configuration to servlet-context.xml, just add a <global-method-security> element to it.

中二柚 2024-11-26 08:19:11

请参阅 Spring Security 常见问题解答(重点是我的)。如果您将切入点应用于服务层,则只需在应用的安全上下文中设置

在 Spring Web 应用程序中,应用程序上下文包含
用于调度程序 servlet 的 Spring MVC bean 通常与
主要应用上下文。它通常定义在一个名为
myapp-servlet.xml,其中“myapp”是分配给 Spring 的名称
web.xml 中的 DispatcherServlet。一个应用程序可以有多个
DispatcherServlet,每个都有自己独立的应用程序上下文。
这些“子”上下文中的 Bean 对其余上下文不可见
应用。 “父”应用程序上下文由
您在 web.xml 中定义的 ContextLoaderListener 对所有人可见
子上下文。该父上下文通常是您定义的位置
您的安全配置,包括
元素)。因此,任何应用于方法的安全约束
这些 Web bean 将不会被强制执行,因为这些 bean 是不可见的
来自 DispatcherServlet 上下文。您需要移动
声明到网络上下文或移动
您想要保护到主应用程序上下文中的 bean。

通常我们建议在服务中应用方法安全性
层而不是单独的 Web 控制器上。

See Spring Security FAQ (emphasis mine). If you apply pointcuts to service layer you only need to set <global-method-security> in your app's security context.

In a Spring web application, the application context which holds the
Spring MVC beans for the dispatcher servlet is often separate from the
main application context. It is often defined in a file called
myapp-servlet.xml, where “myapp” is the name assigned to the Spring
DispatcherServlet in web.xml. An application can have multiple
DispatcherServlets, each with its own isolated application context.
The beans in these “child” contexts are not visible to the rest of the
application. The “parent” application context is loaded by the
ContextLoaderListener you define in your web.xml and is visible to all
the child contexts. This parent context is usually where you define
your security configuration, including the
element). As a result any security constraints applied to methods in
these web beans will not be enforced, since the beans cannot be seen
from the DispatcherServlet context. You need to either move the
declaration to the web context or moved the
beans you want secured into the main application context.

Generally we would recommend applying method security at the service
layer rather than on individual web controllers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文