PreAuthorize 和自定义 AuthenticationFilter with Spring boot

PreAuthorize and custom AuthenticationFilter with Spring boot

我有自定义身份验证过滤器,它创建 PreAuthenticatedAuthenticationToken 并将其存储在安全上下文中。过滤器工作正常,它使用适当的授权权限创建令牌 "ROLE_user" 和 "ROLE_adminuser"。这是我的配置:

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        X509AuthenticationFilter filter = new X509AuthenticationFilter()
        filter.setAuthenticationManager(authenticationManager())
        http.addFilterAfter(filter, SecurityContextPersistenceFilter.class)
        http.authorizeRequests().anyRequest().permitAll()
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean()
        X509AuthenticationFilter filter = new X509AuthenticationFilter()
        filter.setAuthenticationManager(authenticationManager())
        registrationBean.setFilter(filter)
        registrationBean.setEnabled(false)
        return registrationBean
    }

我在 SecurityContextPersistenceFilter 之前插入过滤器,如 Spring security and custom AuthenticationFilter with Spring boot 中所述。

这似乎工作正常,但是,当我尝试向我的控制器方法添加 PreAuthorize 注释时,如下所示:

@Controller
@RequestMapping("/security")
class SecurityController {

    @RequestMapping("/authenticate")
    @PreAuthorize("hasRole('ROLE_user')")
    @ResponseBody
        ResponseEntity<String> authenticate(HttpServletRequest request,     Principal principal) {
        println "authenticate: " +     SecurityContextHolder.getContext().getAuthentication()

        return new ResponseEntity<String>(getPreAuthenticatedPrincipal(request), HttpStatus.OK)
    }

我收到 404 错误。如果我注释掉 PreAuthorize 注释,则方法调用有效,您可以看到我打印出身份验证信息,并且经过身份验证的用户具有 ROLE_user 和 ROLE_adminuser 的授权权限。我不确定我做错了什么。

这是注释掉 "PreAuthorize" 时主体中身份验证对象的打印输出:

authenticate: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@817a0240: Principal: org.springframework.security.ldap.userdetails.LdapUserDetailsImpl@c279eab8: Dn: uid=1,ou=people,dc=cdpe,dc=mil; Username: xxxx@gmail.com; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; CredentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_adminuser, ROLE_user; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_adminuser, ROLE_user authorities: [ROLE_adminuser, ROLE_user]

更新:我取得了一些进步。我将 proxyTargetClass 添加到以下注释中:

 @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)

现在我在调用我的方法时收到 403 Forbidden returns。我不知道那在做什么。

Spring 安全配置一直很繁琐,万无一失的方法只有:

  • 要么是这方面的专家,要么准备好查看源代码,然后你就可以手工完成困难的事情
  • 或尽可能多地使用框架提供的内容,并尽可能使用文档中的示例

对于 X509AuthenticationFilter 的配置,HttpSecurity javadoc 给出了以下示例的方法 x509(适应您的配置 - 原始配置请参阅 javadoc):

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {    

     @Override
     protected void configure(HttpSecurity http) throws Exception {
         http
             .authorizeRequests().anyRequest().permitAll()
             // Example x509() configuration
             .x509();
     }
 }

具有以下指示:方法 returns X509Configurer 用于进一步自定义。

除非您有充分的理由采取不同的做法(如果是这种情况请说明)我强烈建议您坚持使用该方法。

但是在控制器上使用预 post 注释确实是一个坏主意,因为可以直接在 HttpSecurity 配置中完成。它强迫你使用 proxyTargetClass = true.

Pre 和 post 注释通常应用于不需要 proxyTargetClass=true 的服务层方法,因为服务通常通过允许 JDK 代理的接口连接到控制器。

感谢您的帮助。对于这个例子,我被迫重新使用已经工作的 Spring 安全自定义过滤器。我只是想让它在 spring-boot 上下文中工作。

在上面的代码中添加 proxyTargetClass = true 似乎解决了这个问题。