[英]Spring java annotation-based config won't work, but xml-based config does?
[英]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
设置为带有UsernamePasswordAuthenticationToken
的SimpleGrantedAuthority
列表。 这是配置类:
@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.