Spring:通过java配置在Controller层启用全局方法安全

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21554075/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:21:40  来源:igfitidea点击:

Spring: Enable global method security in Controller layer by java config

javaspringspring-mvcspring-securityspring-java-config

提问by gipinani

I'm trying to migrate my xml servlet config to java config.

我正在尝试将我的 xml servlet 配置迁移到 java 配置。

The below config is my servlet configuration, that enables custom security annotations on Controller layer.

下面的配置是我的servlet 配置,它在控制器层启用自定义安全注释。

<security:global-method-security pre-post-annotations="enabled">
    <security:expression-handler ref="expressionHandler"/>
</security:global-method-security>

<bean id="expressionHandler" class="yyy.MyMethodSecurityExpressionHandler" />

I've also have a working spring security xml configuration, that is in order to be replaced by java config, but not now. Here some pieces of my security config:

我也有一个有效的 spring 安全 xml 配置,这是为了被 java 配置替换,但不是现在。这里有一些我的安全配置:

<bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="userDetailsService" />
    </bean>

<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
    <constructor-arg>
         <ref bean="authenticationProvider"/>
    </constructor-arg>
</bean>

<security:authentication-manager>
    <security:authentication-provider user-service-ref="userDetailsService" />
</security:authentication-manager>

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

I want to start to migrate my servlet configenabling security @PreAuthorizeand @PostAuthorizetag in Controller layer.

我想开始迁移我的servlet 配置@PreAuthorize@PostAuthorize以在控制器层启用安全性和标记。

I've found this annotation: @EnableGlobalMethodSecurity(prePostEnabled=true), but putting it on my servlet config:

我找到了这个注解:@EnableGlobalMethodSecurity(prePostEnabled=true),但把它放在我的 servlet 配置中:

@Configuration
@ComponentScan(basePackages= {
        "....."         
})
@EnableGlobalMethodSecurity(prePostEnabled=true)

public class WebappServletConfig extends WebMvcConfigurationSupport {

I get this exception:

我得到这个例外:

java.lang.IllegalArgumentException: Expecting to only find a single bean for type interface org.springframework.security.authentication.AuthenticationManager, but found []

Moreover I don't know how to set my custom expression-handler!

而且我不知道如何设置我的自定义表达式处理程序!

someone with some tips? Thank you

有人有一些提示吗?谢谢

回答by freakman

first of all you need a separate Configuration class like

首先,您需要一个单独的 Configuration 类,例如

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {...

where you need to define

你需要定义的地方

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService);
}

that should help with your exception.

这应该有助于您的例外。

I am not sure how to configure expressionHandler, but seems you can tweak it in configure(WebSecurity web)

我不确定如何配置 expressionHandler,但似乎您可以在 configure(WebSecurity web) 中对其进行调整

@Override
public void configure(WebSecurity web) throws Exception {
    web.expressionHandler().....
}

回答by Rob Winch

Update (after updated question)

更新(更新问题后)

It appears you are encountering SEC-2479. There are a few ways around this. The easiest of which is to use the result of @Autowired for the AuthenticationManager. To do this you must extend GlobalMethodSecurityConfiguration and override the authenticationManager method.

您似乎遇到了SEC-2479。有几种方法可以解决这个问题。其中最简单的是将@Autowired 的结果用于AuthenticationManager。为此,您必须扩展 GlobalMethodSecurityConfiguration 并覆盖 authenticationManager 方法。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Autowired
    private AuthenticationManager am;

    @Override
    protected AuthenticationManager authenticationManager() {
        return am;
    }
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        // ... create and return custom MethodSecurityExpressionHandler ...
        return expressionHander;
    }
}

Original Answer

原答案

You need to configure some sort of Authentication. So you will need to have the following:

您需要配置某种身份验证。因此,您需要具备以下条件:

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .inMemoryAuthentication()
            .withUser("user").password("password").roles("USER");
}

If you are not using web based security, the reference provides an exampleof how to configure the method security expression handler.

如果您不使用基于 Web 的安全性,参考提供了如何配置方法安全性表达式处理程序的示例

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        // ... create and return custom MethodSecurityExpressionHandler ...
        return expressionHander;
    }
}

If you are only wanting a custom method expression handler to provide a permission evaluator, then you only need to create a PermissionEvaluator bean like this:

如果您只想要一个自定义方法表达式处理程序来提供权限评估器,那么您只需要像这样创建一个 PermissionEvaluator bean:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig {
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
    @Bean
    public PermissionEvaluator permissionEvaluator() {
        // ... create and return custom PermissionEvaluator ...
        return permissionEvaluator;
    }
}