繁体   English   中英

结合使用Java配置和Spring Security进行基于注释的角色检查和基本HTTP身份验证

[英]Using Java config with Spring Security for annotation-based role checks and Basic HTTP Auth

我试图在我的一个控制器上完成基于注释的(使用@PreAuthorize )权限检查。 我正在使用Java config,并且具有一个SecurityConfig类扩展了WebSecurityConfigurerAdapter

我还使用基本HTTP身份验证来获取需要授权的方法。

但是-问题是,我希望SecurityConfig确定需要使用antPattern()或类似方法进行身份验证的方法。 这就是注释的目的!

如何配置SecurityConfig类,以便它对带有@PreAuthorize方法正确使用HTTP Basic身份验证和配置的AuthenticationManager ,并允许匿名访问附加任何安全注释的控制器方法?

当我尝试这个(尝试#1)时:

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
    }

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

我未受保护的方法失败,并显示以下信息:

Full authentication is required to access this resource

我的受保护(但经过正确认证)的测试失败,并出现以下问题:

Error: Expected CSRF token not found. Has your session expired?

当我尝试这个(尝试#2)时:

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

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

我的未受保护的方法失败,并显示302状态代码,并重定向到/login ,而我的受保护/身份验证方法失败,并显示:

Error: Expected CSRF token not found. Has your session expired?

当我尝试这个(尝试#3)时:

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic();
    }

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

我的身份验证方法正常工作。 (呜呼!)但是,我的未受保护的方法失败并显示401因为我的HttpSecurity似乎已配置为在通过身份验证时才允许访问-不管控制器方法是否使用@PreAuthorize注释。

当我尝试这个(尝试#4)时:

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests().anyRequest().permitAll();
    }

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

我的不受保护的方法可以正常工作(允许访问),但是我的身份验证方法(无论它们是否具有正确的HTTP身份验证)都将失败,并显示状态码403

Error: Access Denied

我的身份验证测试方法失败了403它使用MockMvc并使用标头发送请求:

{Content-Type=[application/json], Accept=[application/json], Authorization=[Basic Y3JhaWc6Y3JhaWdwYXNz]}

我已对其进行解码和验证,以及带有方法POST的URL /api/item ,该方法应以相应的方法为目标:

@RequestMapping(value = "/api/item", method = { RequestMethod.POST })
@PreAuthorize("hasRole('ROLE_USER')")
public void postNewItem(HttpServletRequest request, HttpServletResponse response) {
    ...
}

我做了类似的事情,唯一的区别是我有一些非常定制的身份验证方法。 如果您唯一想检查用户角色, @PreAuthorize在控制器方法上使用@Secured而不是@PreAuthorize ,例如

@Secured({"ROLE_SOMEROLE"})
public void doSomething(...) {
}

角色在AuthenticationProvider设置为带有UsernamePasswordAuthenticationTokenSimpleGrantedAuthority列表。 这是配置类:

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled=true)
public class SecurityConfig  extends WebSecurityConfigurerAdapter {

@Autowired
private AuthenticationProvider authProvider;

@Autowired
private AuthenticationEntryPoint authenticationEntryPoint;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
        throws Exception {
    auth.authenticationProvider(authProvider);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    // Had some other calls for CORS ajax requests.
    http.authorizeRequests()
            .antMatchers("/logout")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .httpBasic()
            .authenticationEntryPoint(authenticationEntryPoint)
            .csrf()
            .disable();
}

}

如果您的方法使用@Secured注释,并且当前用户未指定角色,则客户端将收到403响应,否则请求将通过。 如果您尝试运行单元测试,则可以在bean上使用@Profile('test')并将AuthenticationProvider与硬编码数据一起使用。 这是有关这种方法的文章: https : //spring.io/blog/2011/02/14/spring-3-1-m1-introducing-profile/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM