Spring security SpringSecurity with Security Context MockMvc OAuth2始终未经授权
我按照以下链接尝试测试OAuth2@PreAuthorise(例如hasAnyRole('ADMIN','test'),但我无法通过任何测试,甚至无法进行身份验证 当我尝试使用管理员(或任何角色)访问端点时它永远不会正确地进行身份验证。如果我遗漏了一些明显的东西,我似乎拥有了示例中的所有内容。我还尝试了另一种替代方法,使用特定于OAuth的身份验证代替WithSecurity Context工厂,但仍然没有成功。如果有任何帮助,我们将不胜感激 和 我正在测试我的控制器Spring security SpringSecurity with Security Context MockMvc OAuth2始终未经授权,spring-security,spring-boot,spring-security-oauth2,spring-test,spring-oauth2,Spring Security,Spring Boot,Spring Security Oauth2,Spring Test,Spring Oauth2,我按照以下链接尝试测试OAuth2@PreAuthorise(例如hasAnyRole('ADMIN','test'),但我无法通过任何测试,甚至无法进行身份验证 当我尝试使用管理员(或任何角色)访问端点时它永远不会正确地进行身份验证。如果我遗漏了一些明显的东西,我似乎拥有了示例中的所有内容。我还尝试了另一种替代方法,使用特定于OAuth的身份验证代替WithSecurity Context工厂,但仍然没有成功。如果有任何帮助,我们将不胜感激 和 我正在测试我的控制器 @RestContro
@RestController
@RequestMapping("/bookmark/")
public class GroupBookmarkController {
@Autowired
BookmarkService bookmarkService;
/**
* Get list of all bookmarks
*/
@RequestMapping(value = "{groupId}", method = RequestMethod.GET)
@PreAuthorize("hasAnyRole(['ADMIN', 'USER'])")
public ResponseEntity<List<Bookmark>> listAllGroupBookmarks(@PathVariable("groupId") String groupId) throws BookmarkNotFoundException {
List<Bookmark> bookmarks = bookmarkService.findAllBookmarksByGroupId(groupId);
return new ResponseEntity<>(bookmarks, HttpStatus.OK);
}
...
}
我的书签服务应用程序
@SpringBootApplication
@EnableResourceServer
public class BookmarkServiceApplication {
public static void main(String[] args) {
SpringApplication.run(BookmarkServiceApplication.class, args);
}
}
我的WithSecurity ContextFactory
public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory<WithMockCustomUser> {
@Override
public SecurityContext createSecurityContext(WithMockCustomUser customUser) {
SecurityContext context = SecurityContextHolder.createEmptyContext();
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
UserDetails principal = new User(customUser.username(), "password", true, true, true, true, grantedAuthorities);
Authentication authentication = new UsernamePasswordAuthenticationToken(
principal, principal.getPassword(), principal.getAuthorities());
context.setAuthentication(authentication);
return context;
}
}
根据@RobWinch的回复
Hi@RobWinch我试过你关于无状态标志的建议,这有助于回答部分问题 您不再需要担心是否在无状态模式下运行 为什么我仍然需要添加无状态false,这是一个bug还是我们使用它的方式略有不同 我需要做的另一件事是将OAuth2Request和OAuth2Authentication添加到WithSecurityContextFactory中,如下所示
public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory<WithMockOAuthUser> {
@Override
public SecurityContext createSecurityContext(WithMockOAuthUser withClient) {
// Get the username
String username = withClient.username();
if (username == null) {
throw new IllegalArgumentException("Username cannot be null");
}
// Get the user roles
List<GrantedAuthority> authorities = new ArrayList<>();
for (String role : withClient.roles()) {
if (role.startsWith("ROLE_")) {
throw new IllegalArgumentException("roles cannot start with ROLE_ Got " + role);
}
authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
}
// Get the client id
String clientId = withClient.clientId();
// get the oauth scopes
String[] scopes = withClient.scope();
Set<String> scopeCollection = Sets.newSet(scopes);
// Create the UsernamePasswordAuthenticationToken
User principal = new User(username, withClient.password(), true, true, true, true, authorities);
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(),
principal.getAuthorities());
// Create the authorization request and OAuth2Authentication object
OAuth2Request authRequest = new OAuth2Request(null, clientId, null, true, scopeCollection, null, null, null,
null);
OAuth2Authentication oAuth = new OAuth2Authentication(authRequest, authentication);
// Add the OAuth2Authentication object to the security context
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(oAuth);
return context;
}
}
带有MockCustomUserSecurityContextFactory的公共类使用Security ContextFactory实现{
@凌驾
public SecurityContext createSecurityContext(带MockOAuthuser和客户端){
//获取用户名
字符串username=withClient.username();
如果(用户名==null){
抛出新的IllegalArgumentException(“用户名不能为null”);
}
//获取用户角色
列表权限=新建ArrayList();
for(字符串角色:withClient.roles()){
if(role.startsWith(“role_”)){
抛出新的IllegalArgumentException(“角色不能以ROLE_uGot”+ROLE开头);
}
添加(新的SimpleGrantedAuthority(“角色+角色”);
}
//获取客户端id
字符串clientId=withClient.clientId();
//获取oauth范围
字符串[]scopes=withClient.scope();
Set scopeCollection=Set.newSet(scopes);
//创建UsernamePasswordAuthenticationToken
用户主体=新用户(用户名,withClient.password(),true,true,true,authorities);
Authentication Authentication=新用户名PasswordAuthenticationToken(主体,主体.getPassword(),
principal.getAuthorities());
//创建授权请求和OAuth2Authentication对象
OAuth2Request authRequest=新的OAuth2Request(null,clientId,null,true,scopeCollection,null,null,null,
无效);
OAuth2Authentication oAuth=新的OAuth2Authentication(authRequest,authentication);
//将OAuth2Authentication对象添加到安全上下文中
SecurityContext上下文=SecurityContextHolder.createEmptyContext();
setAuthentication(oAuth);
返回上下文;
}
}
问题在于,如果SecurityContext被标记为无状态,则会清除它。要解决此问题,请将其配置为允许在外部填充状态(即无状态=false)。要添加更多信息,如何将无状态设置为false:
在ResourceServerConfigurerAdapter中,执行以下操作:
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.stateless(false);
}
这对我很有用。WithMockOAuthUser的代码在哪里?它与Security ContextFactory有关?@RobWinch抱歉,这是一个打字错误,实际上WithMockCustomUser是一个打字错误,让我胡思乱想,同样的问题也存在。我有另一个界面,它创建了OAuth身份验证,而不是用户名密码身份验证什么您的安全配置看起来像吗?具体来说,web和方法安全配置看起来像什么?@RobWinch我实际上没有一个默认配置运行,这是一个微服务,在带有配置的auth服务的网关后面进行通信。这些测试是在与AuthService隔离的情况下运行的我仍然有一个配置?@revilo如果我可以问的话,你是否可以与你的测试环境共享一个存储库?我正在尝试测试spring-security-oauth2,除了401之外,我什么都得不到。你的文章是帮助我理解得最多的一篇文章。使用spring-security和spring-security-oauth2的项目测试还不存在。它是太好了。提前感谢Hi@RobWinch我用无状态标志尝试了你的建议,这有助于部分答案。但是在你对这个问题的回答[Spring OAuth and Boot Integration Test]()中你提到“你不再需要担心是否在无状态模式下运行”为什么它是必需的我需要这个,这是一个错误还是我们使用它有点不同。我已经更新了答案,因为我已经用完了这里的字符Spring Security OAuth处理无状态的不同于Spring Security,因此该语句不适用于OAuth(不幸的是).在上面的示例中,您到底是如何将其设置为false的?@RobWinch亲爱的rob,我们已经尝试了好几天来测试spring-security-oauth2,我们也遇到了401个错误。spring-security-oauth2没有任何示例,我们需要一个。有没有办法获得示例或其他信息?
public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory<WithMockOAuthUser> {
@Override
public SecurityContext createSecurityContext(WithMockOAuthUser withClient) {
// Get the username
String username = withClient.username();
if (username == null) {
throw new IllegalArgumentException("Username cannot be null");
}
// Get the user roles
List<GrantedAuthority> authorities = new ArrayList<>();
for (String role : withClient.roles()) {
if (role.startsWith("ROLE_")) {
throw new IllegalArgumentException("roles cannot start with ROLE_ Got " + role);
}
authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
}
// Get the client id
String clientId = withClient.clientId();
// get the oauth scopes
String[] scopes = withClient.scope();
Set<String> scopeCollection = Sets.newSet(scopes);
// Create the UsernamePasswordAuthenticationToken
User principal = new User(username, withClient.password(), true, true, true, true, authorities);
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(),
principal.getAuthorities());
// Create the authorization request and OAuth2Authentication object
OAuth2Request authRequest = new OAuth2Request(null, clientId, null, true, scopeCollection, null, null, null,
null);
OAuth2Authentication oAuth = new OAuth2Authentication(authRequest, authentication);
// Add the OAuth2Authentication object to the security context
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(oAuth);
return context;
}
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.stateless(false);
}