我目前正在使用Spring Security的OAuth2来实现跨多个微服务的授权。我们的AuthService
使用OAuth2令牌等执行所有身份验证,并可以创建用户。
考虑两个客户端:客户端A和客户端B.
客户A有权限:CREATE_USER, CREATE_POST
客户B有权限:READ_USER
(是的,我们可以使用范围代替,但这只是一个例子!)
目的:
只允许具有权限CREATE_USER
的客户端A创建用户。用户通过发布到/users
来创建。
问题:
问题是当我向/ users端点发送POST请求并使用客户端A的基本身份验证标头时,找不到CREATE_USER
权限,因为请求命中AnonymousAuthenticationFilter
而且只有ROLE_ANONYMOUS
找到的权限是10:38:34.852 [http-nio-9999-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /users; Attributes: [#oauth2.throwOnError(#oauth2.hasAuthority('CREATE_USER))]
10:38:34.852 [http-nio-9999-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - 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 o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@a63e3e8, returned: -1
10:38:34.856 [http-nio-9999-exec-1] DEBUG 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
,我收到以下内容:
CREATE_VIEWER
一个令人难以置信的hacky解决方案是注册一个自定义安全过滤器,该过滤器读取基本auth标头并验证客户端的名称是否等于客户端A,但这不适用于第三个客户端,即客户端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")
}
客户端配置
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
}
WebSecurityConfigurerAdaptor impl
function chk()
{
var sname = $('#app_for_class').find(":selected").text();
if(sname==='LKG')
{
$('#date').datetimepicker({
minDate:'2013-01-1',
maxDate:'2015-11-30',
});
}
}