我们有以下安全控制器:
@RestController
@RequestMapping("/api/employee")
public class EmployeeController {
@GetMapping
@PreAuthorize("#oauth2.hasScope('edit') OR hasRole('ADMIN')")
public String getForAdmin(@AuthenticationPrincipal Principal principal) {
return employeeService.getForAdmin(principal)
}
}
安全按预期工作。我收到了来自授权服务器的 jwt 访问令牌,并且带有标题“授权承载 xxxx.yyyy.zzzz”的请求,我可以调用这个控制器。
资源服务器已配置非常基本的身份验证
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(httpSecurity -> httpSecurity
.anyRequest().authenticated()
);
}
接下来,我尝试为员工控制器编写集成测试,以确保安全工作正常,如下所示:
// configure mock mvc with security
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
// call secured endpoint and with specific authentication
mockMvc.perform(get("/api/employee")
.with(jwt())
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk());
我发现它存在JwtRequestPostProcessor
于我在示例中指定的位置,但我不知道如何告诉这个模拟的jwt
范围和角色。我至少尝试过这样的角色:
jwt().authorities(new SimpleGrantedAuthority("ROLE_ADMIN"))
但它不起作用,我总是得到 401 错误。
编辑:这是我在启用安全调试级别后发现的日志:
2020-02-14 11:42:18.167 DEBUG 2094 --- [ main] o.s.security.web.FilterChainProxy : /api/employee at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
2020-02-14 11:42:18.167 DEBUG 2094 --- [ main] o.s.s.o.p.a.BearerTokenExtractor : Token not found in headers. Trying request parameters.
2020-02-14 11:42:18.167 DEBUG 2094 --- [ main] o.s.s.o.p.a.BearerTokenExtractor : Token not found in request parameters. Not an OAuth2 request.
2020-02-14 11:42:18.167 DEBUG 2094 --- [ main] p.a.OAuth2AuthenticationProcessingFilter : Clearing security context.
2020-02-14 11:42:18.167 DEBUG 2094 --- [ main] p.a.OAuth2AuthenticationProcessingFilter : No token in request, will continue chain.
2020-02-14 11:42:18.167 DEBUG 2094 --- [ main] o.s.security.web.FilterChainProxy : /api/employee at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2020-02-14 11:42:18.167 DEBUG 2094 --- [ main] o.s.security.web.FilterChainProxy : /api/employee at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2020-02-14 11:42:18.168 DEBUG 2094 --- [ main] o.s.security.web.FilterChainProxy : /api/employee at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2020-02-14 11:42:18.168 DEBUG 2094 --- [ main] o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@94907bf0: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
2020-02-14 11:42:18.168 DEBUG 2094 --- [ main] o.s.security.web.FilterChainProxy : /api/employee at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2020-02-14 11:42:18.169 DEBUG 2094 --- [ main] o.s.security.web.FilterChainProxy : /api/employee at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2020-02-14 11:42:18.169 DEBUG 2094 --- [ main] o.s.security.web.FilterChainProxy : /api/employee at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2020-02-14 11:42:18.169 DEBUG 2094 --- [ main] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /api/employee; Attributes: [#oauth2.throwOnError(authenticated)]
2020-02-14 11:42:18.169 DEBUG 2094 --- [ main] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@94907bf0: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2020-02-14 11:42:18.173 DEBUG 2094 --- [ main] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@2f6e92ca, returned: -1
2020-02-14 11:42:18.176 DEBUG 2094 --- [ main] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>