【问题标题】:@PreAuthorize annotation in Spring Security doesn't work. Might be misconfigured .xml fileSpring Security 中的 @PreAuthorize 注释不起作用。可能是配置错误的 .xml 文件
【发布时间】:2016-01-30 17:11:31
【问题描述】:

我正在使用带有 AngularJS 的 Spring Security(Spring Boot 应用程序),并且我正在尝试根据用户授予的权限来允许/拒绝对特定映射的访问。

用户.java

public class User implements UserDetails {
    ...
    private String username;
    private String password;
    private boolean enabled;
    private List<GrantedAuthority> grantedAuthorities;

    public User(...) {...}

    private class Permission implements GrantedAuthority {
        String permission;

        public Permission(String permission) {
            this.permission = permission;
        }

        @Override
        public String getAuthority() {
            return permission;
        }
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return grantedAuthorities;
    }
    ...
}

另外,我有自己的UserDetailsService 实现(方法loadUserByUsername(String username)),它使用数据库中的数据填充用户数据。

前面提到的映射是:

@RequestMapping("yes")
public void doesHaveAuthority() {yes();}

@PreAuthorize("hasAuthority('10001')")
private void yes() {}

@RequestMapping("no")
public void doesntHaveAuthority() {no();}

@PreAuthorize("hasAuthority('00000')")
private void no() {}

如果用户确实拥有“10001”权限,但没有“00000”权限,则应允许访问/yes,但不应允许访问/no。不幸的是,这两条路径都是允许的。

我有 spring-security-config 作为 maven 依赖项,正如提到的 here

我的 WEB-INF/web.xml

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <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>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/security.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

</web-app>

和WEB-INF/security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:context="http://www.springframework.org/schema/context"
    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.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security.xsd">

    <context:component-scan base-package="com.mycompany.project" />

    <global-method-security pre-post-annotations="enabled" />

</beans:beans>

所以,总结一下:UserDetailsS​​ervice 实现工作(我可以使用用户凭据登录,并且记录器打印授予权限,所以我知道他们在那里),但用户可以访问 yes 和 @987654333 @paths 实际上他/她不应该能够访问/no,因为他/她没有权限(permission)“00000”。

也许我的 xml 配置不正确或根本没有被读取。

感谢您的宝贵时间

更新 正如 M. Deinum 在 cmets 中所说,Spring Boot 忽略 web.xml 和 security.xml 文件。解决的办法是修改SecurityConfiguration扩展WebSecurityConfigurerAdapter,并添加相应的antMatchers和相应的权限。

例子:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic().and()
        .authorizeRequests()
        .antMatchers("/login.html", "/index.html", "/").permitAll()
        .antMatchers("/yes").hasAuthority("10001")
        .antMatchers("/no").hasAuthority("00000")
        .anyRequest()
        .authenticated().and()
        .addFilterAfter(new CSRFHeaderFilter(), CsrfFilter.class)
        .csrf().csrfTokenRepository(csrfTokenRepository());
}

【问题讨论】:

  • 使用 Spring AOP 应用安全性,这意味着使用了代理,这导致您的注释无用。只有对对象的方法调用通过代理,您正在进行内部方法调用,所以没有代理,没有安全性。
  • @M.Deinum 我是 Spring Security 的新手,所以你能解释一下吗?我有哪些选择?我知道internal method calls 是什么意思,我可以轻松地将@PreAuth 注释移动到@RequestMapping,但这并不能解决任何问题。如果您能指出另一个 SO 问题/答案或博客文章,我将不胜感激
  • 您还需要在包含带有注释的bean 的上下文中具有&lt;global-method-security ... /&gt; 标记。我假设您还有一个DispatcherServlet,它负责包含@RequestMapping@Controllers。在父上下文 (ContextLoaderListener one) 中定义的 AOP 不会影响子上下文 (DispatcherServlet) 中的 bean。
  • 我确实有&lt;global-method-security pre-post-annotations="enabled" /&gt;,但我不确定是否正在读取 xml,即使在 web.xml 中指定了配置路径。我没有任何DispatcherServlet 的...我不知道我需要一个,因为一切似乎都很好(而且Spring guide 没有说我需要一个)。
  • 您是否遵循指南?由于该指南使用 Spring Boot,并且基本上丢弃了您的 web.xml 和 xml 配置。您需要将@EnableGlobalMethodSecurity 添加到您的应用程序类中。

标签: spring spring-security spring-boot pre-authentication


【解决方案1】:

用户“我们是博格”要求我发布解决方案作为答案,所以这里是:

基本上,由于我的应用程序是 Spring Boot 应用程序,因此它被忽略(忽略了我的 .xml 配置文件)。解决方案非常简单:扩展WebSecurityConfigurerAdapter 并覆盖configure(HttpSecurity) 方法。覆盖它时,请确保用户具有访问路径(antMatchers)的权限和/或权限。它应该看起来像这样:

SecurityConfiguration.java

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.httpBasic().and()
            .authorizeRequests()
            .antMatchers("/login.html", "/index.html", "/").permitAll()
            .antMatchers("/yes").hasAuthority("10001")
            .antMatchers("/no").hasAuthority("00000")
            .anyRequest().authenticated();
    }

}

您将不再需要 @PreAuthorize 注释,也不再需要 .xml 配置文件(security.xml、web.xml 等...)

祝你好运;)

【讨论】:

  • 多角色多uri的例子可以是antMatchers("/drug/deleteDrug/**","/drug/editDrug/**","/drug/saveDrugs/**"," /drug/newDrug/**").hasAnyAuthority("ADMIN","MANAGER")
猜你喜欢
  • 2011-07-10
  • 2011-06-28
  • 2015-12-09
  • 2021-09-27
  • 1970-01-01
  • 1970-01-01
  • 2015-10-12
  • 1970-01-01
  • 2014-01-01
相关资源
最近更新 更多