Spring Security:基于客户机权限的安全端点
我目前正在使用Spring Security的OAuth2来实现跨多个微服务的授权。 我们的AuthService
使用OAuth2令牌执行所有的身份验证,并可以创建用户。
考虑两个客户端:客户端A和客户端B.
客户端A具有权限: CREATE_USER, CREATE_POST
客户端B具有权限: READ_USER
(是的,我们可以使用范围,但这只是一个例子!)
目标:
只有拥有权限CREATE_USER
客户端A才能被允许创建一个用户。 用户正在通过张贴到/users
创建。
问题:
问题是,当我发送一个POST请求到用户A的基本身份验证头的/用户端点时, CREATE_USER
权限,因为请求命中了AnonymousAuthenticationFilter
,唯一发现的权限是ROLE_ANONYMOUS
,我收到以下内容:
10:38:34.852 [http-nio-9999-exec-1] DEBUG osswaiFilterSecurityInterceptor - Secure object: FilterInvocation: URL: /users; Attributes: [#oauth2.throwOnError(#oauth2.hasAuthority('CREATE_USER))] 10:38:34.852 [http-nio-9999-exec-1] DEBUG osswaiFilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS 10:38:34.854 [http-nio-9999-exec-1] DEBUG ossaccess.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@a63e3e8, returned: -1 10:38:34.856 [http-nio-9999-exec-1] DEBUG osswaExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point org.springframework.security.access.AccessDeniedException: Access is denied
一个令人难以置信的解决方法是注册一个自定义的安全过滤器,读取基本的auth头,并验证客户端的名称是否等于客户端A,但这不会为第三个客户端,即也具有CREATE_VIEWER
权限的客户端C在这里验证的名称,而不是当局。
// UsersController.kt @PostMapping("/users") @ResponseStatus(HttpStatus.OK) @ResponseBody fun createUser(): String { return "Created user!" }
客户端配置
override fun configure(clients: ClientDetailsServiceConfigurer?) { clients!!.inMemory() .withClient("ClientA") .scopes("all") .authorities("CREATE_USER", "CREATE_POST") .authorizedGrantTypes("refresh_token", "password") .and() .withClient("ClientB") .scopes("all") .authorities("READ_USER") .authorizedGrantTypes("refresh_token", "password") }
WebSecurityConfigurerAdaptor impl
override fun configure(http: HttpSecurity) { http.requestMatchers().antMatchers("/oauth/authorize", "/oauth/confirm_access") .and() .authorizeRequests() .antMatchers("/users").access("hasAuthority('CREATE_USER')") .anyRequest().authenticated() .and() .csrf().disable() } override fun configure(auth: AuthenticationManagerBuilder) { auth.authenticationProvider(authenticationProvider()) } @Bean open fun authenticationProvider(): DaoAuthenticationProvider { val authProvider = DaoAuthenticationProvider() authProvider.setUserDetailsService(userCredentialService) authProvider.setPasswordEncoder(passwordEncoderService) return authProvider }