使用Spring启动PreAuthorize和自定义AuthenticationFilter

时间:2015-04-21 14:24:21

标签: spring-security 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。我不确定我做错了什么。

这是&#34; PreAuthorize&#34;在主体中打印出身份验证对象的时间。被注释掉了:

  

的authenticate:   org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@817a0240:   主要:   org.springframework.security.ldap.userdetails.LdapUserDetailsImpl@c279eab8:   Dn:uid = 1,ou =人,dc = cdpe,dc = mil;用户名:xxxx@gmail.com;   密码保护];启用:true; AccountNonExpired:true;   CredentialsNonExpired:true; AccountNonLocked:true;诚然   权限:ROLE_adminuser,ROLE_user;证书:[保护];   认证:真实;细节:   org.springframework.security.web.authentication.WebAuthenticationDetails@957e:   RemoteIpAddress:127.0.0.1; SessionId:null;授权机构:   ROLE_adminuser,ROLE_user权限:[ROLE_adminuser,ROLE_user]

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

 @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)

现在,当我打电话给我的方法时,我获得了403 Forbidden返回。我不知道那是做什么的。

2 个答案:

答案 0 :(得分:7)

嗯,Spring Security的配置总是很乏味,唯一的方式是:

  • 要么是它的专家,要准备好查看来源,然后你就可以用手做
  • 尽可能使用文档中的示例尽可能多地使用框架提供的内容

对于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();
     }
 }
带有以下指示的

:方法返回X509Configurer以进行进一步的自定义。

除非你有充分的理由采取不同的行动(如果是这种情况请说出来),我强烈建议你坚持使用这种方法。

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

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

答案 1 :(得分:0)

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

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