我正在尝试使用基于注释的(使用@PreAuthorize
)权限检查来完成我的控制器之一。 我正在使用Java配置,并且有一个扩展WebSecurityConfigurerAdapter
的SecurityConfig
类。
我还在使用基本HTTP身份验证来访问需要授权的方法。
但是,问题是,我不想使用antPattern()
或类似的方法让SecurityConfig
确定哪些方法需要进行身份验证。这就是注释的作用所在!
我应该如何配置我的SecurityConfig
类,以便它正确地使用HTTP基本身份验证和已配置的AuthenticationManager
来处理带有@PreAuthorize
的方法,并允许匿名访问没有任何安全注释的控制器方法?
当我尝试这样做(尝试#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");
}
}
我的未受保护的方法出现以下错误:
需要完整认证才能访问此资源
而我的受保护方法(但已正确认证)的测试出现以下错误:
错误:找不到预期的CSRF令牌。您的会话是否已过期?
当我尝试这样做(第二次尝试):
@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?
当我尝试第三次时:@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");
}
}
我的认证方法正常工作。(万岁!) 但是,我的未受保护的方法由于我的HttpSecurity看起来已经配置成只有在经过身份验证后才允许访问 - 无论控制器方法是否带有@PreAuthorize注释,因此失败并返回401错误。 当我尝试这样做时(第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
我的身份验证测试方法使用
MockMvc
,并使用以下标头发送请求:{Content-Type=[application/json], Accept=[application/json], Authorization=[Basic Y3JhaWc6Y3JhaWdwYXNz]}
我已对其进行解码和验证,并使用URL
/api/item
和方法POST
,应该定位到相应的方法:@RequestMapping(value = "/api/item", method = { RequestMethod.POST })
@PreAuthorize("hasRole('ROLE_USER')")
public void postNewItem(HttpServletRequest request, HttpServletResponse response) {
...
}