我尝试在我的某个控制器上完成基于注释(使用@PreAuthorize
)权限检查。我正在使用Java配置,并且SecurityConfig
类扩展为WebSecurityConfigurerAdapter
。
我还使用基本HTTP身份验证来获取需要授权的方法。
但是 - 问题是,我没有希望SecurityConfig
确定哪些方法需要使用antPattern()
或类似的身份验证。这就是注释的用途!
如何配置我的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");
}
}
我未受保护的方法失败了:
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]}
我已对其进行了解码和验证,以及使用方法/api/item
的网址POST
,该网址应定位相应的方法:
@RequestMapping(value = "/api/item", method = { RequestMethod.POST })
@PreAuthorize("hasRole('ROLE_USER')")
public void postNewItem(HttpServletRequest request, HttpServletResponse response) {
...
}
答案 0 :(得分:0)
我做过类似的事情,唯一的区别是我有一些非常自定义的身份验证方法。如果你想要的只是检查用户角色,你应该在控制器方法上使用@Secured
而不是@PreAuthorize
,例如。
@Secured({"ROLE_SOMEROLE"})
public void doSomething(...) {
}
将AuthenticationProvider
中的角色设置为SimpleGrantedAuthority
与UsernamePasswordAuthenticationToken
的列表。
这是配置类:
@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/