haw*_*awi 5 spring-security oauth-2.0 spring-boot
TL; DR:如何根据用户的access_token在资源服务器端(即没有JWT)分配用户自定义角色/权限?
整个故事:我有一个正在运行的Auth服务器和一个客户端(即SPA),可以从Auth服务器获取access_token。借助该access_token,客户端可以在我的资源服务器(与Auth服务器分离)上请求数据。资源服务器可以使用access_token从Auth服务器获取用户名。
我可以通过将Authentication对象注入到这样的方法中来访问代码中的用户名:
@RequestMapping("/ping")
fun pingPong(auth: Authentication): String = "pong, " + auth.name
Run Code Online (Sandbox Code Playgroud)
我的问题是如何auth.authorities向该对象添加我的自定义角色或权限(-仅USER_ROLE),该对象将根据用户名在资源服务器上而不是Auth服务器上进行管理。
我尝试了几种方法来做,但是没有一个帮助。最有希望的是:
@Configuration
@EnableWebSecurity
@EnableResourceServer
class ResourceServerConfigurer(val userDetailsService: MyUserDetailsService) : ResourceServerConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http.userDetailsService(userDetailsService) // userDetailsService is autowired
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests()
.antMatchers("/", "/index.html").permitAll()
.anyRequest().authenticated()
}
}
Run Code Online (Sandbox Code Playgroud)
和我的自定义UserDetailsService:
@Service
class UserDetailsService : org.springframework.security.core.userdetails.UserDetailsService {
override fun loadUserByUsername(username: String): UserDetails {
return org.springframework.security.core.userdetails.User(username, "password", getAuthorities(username))
}
private fun getAuthorities(user: String): Set<GrantedAuthority> {
val authorities = HashSet<GrantedAuthority>()
authorities.addAll(listOf(
SimpleGrantedAuthority("ROLE_ONE"), //let's grant some roles to everyone
SimpleGrantedAuthority("ROLE_TWO")))
return authorities
}
}
Run Code Online (Sandbox Code Playgroud)
一切正常(我是说我已成功通过身份验证),但我仍然只有ROLE_USER。接下来,我尝试提供一个AbstractUserDetailsAuthenticationProvider的自定义实现:
@Bean
fun authenticationProvider(): AbstractUserDetailsAuthenticationProvider {
return object : AbstractUserDetailsAuthenticationProvider() {
override fun retrieveUser(username: String, authentication: UsernamePasswordAuthenticationToken): UserDetails {
return User(username, "password", getAuthorities(username))
}
private fun getAuthorities(user: String): Set<GrantedAuthority> {
val authorities = HashSet<GrantedAuthority>()
authorities.addAll(listOf(
SimpleGrantedAuthority("ROLE_ONE"),
SimpleGrantedAuthority("ROLE_TWO")))
return authorities
}
override fun additionalAuthenticationChecks(userDetails: UserDetails, authentication: UsernamePasswordAuthenticationToken?) {
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果相同,仅存在ROLE_USER。
我真的很感谢你们提出的任何想法,这些想法是在验证access_token和从Auth服务器获取用户名后如何向Authentication对象添加一些角色。
OP 的解决方案。
首先,我需要提供自定义PrincipalExtractor和AuthoritiesExtractor实现。但是为了让 Spring 使用它们,在配置中必须不使用它们security.oauth2.resource.token-info-uri,而是使用security.oauth2.resource.user-info-uri它们(我真的没想到这是我问题的根源之一)。
最后,安全配置必须在 中完成ResourceServerConfigurerAdapter,而不是在WebSecurityConfigurerAdapter.
最终代码如下所示:
@SpringBootApplication
@RestController
class MyApplication {
@RequestMapping("/ping")
fun pingPong(user: Authentication): String {
return "pong, " + user.name + " - " + user.authorities.joinToString()
}
}
@Configuration
@EnableWebSecurity
@EnableResourceServer
class ResourceServerConfigurer : ResourceServerConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests()
.antMatchers("/", "/index.html").permitAll()
.anyRequest().authenticated()
}
@Bean
fun principalExtractor() = PrincipalExtractor {
return@PrincipalExtractor it["name"]
}
@Bean
fun authoritiesExtractor() = AuthoritiesExtractor {
return@AuthoritiesExtractor AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ONE,ROLE_TWO")
}
}
fun main(args: Array<String>) {
SpringApplication.run(MyApplication::class.java, *args)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2262 次 |
| 最近记录: |