Spring 在资源服务器上启动 OAuth2 自定义角色 [英] Spring boot OAuth2 custom roles on Resource server

查看:63
本文介绍了Spring 在资源服务器上启动 OAuth2 自定义角色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL;DR:如何根据用户的 access_token 在资源服务器端(即没有 JWT)为用户分配自定义角色/权限?

TL;DR: How to assign users custom roles/authorities on Resource server side (that means without JWT) based on their access_token?

整个故事:我有一个正在工作的 Auth 服务器和一个客户端(即 SPA),它可以从 Auth 服务器获取 access_token.使用该 access_token,客户端可以在我的资源服务器(与身份验证服务器分离)上请求数据.资源服务器可以使用 access_token 从 Auth 服务器获取用户名.

The whole story: I have a working Auth server and a client (which is SPA), which can obtain access_token from the Auth server. With that access_token the client can request data on my Resource server (which is separated from Auth server). The Resource server can get username from Auth server using the access_token.

我可以通过将 Authentication 对象注入到这样的方法中来访问代码中的用户名:

I can access the username in code by injection Authentication object into method like this:

@RequestMapping("/ping")
fun pingPong(auth: Authentication): String = "pong, " + auth.name

我的问题是如何将我的自定义角色或权限(auth.authorities - 只有 USER_ROLE)添加到将在资源服务器而不是身份验证服务器上管理的对象中,基于用户名.

My question is how to add my custom roles or authorities (auth.authorities - there is only USER_ROLE) to this object which would be managed on the Resource server, not Auth server, based on the username.

我尝试了几种方法来做到这一点,但都没有帮助.最有希望的是这个:

I have tried several ways to do it but none has helped. The most promising was this:

@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()
    }
}

还有我的自定义 UserDetailsS​​ervice:

And my custom 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
    }
}

一切正常(我的意思是我已成功通过身份验证),但我仍然只有 ROLE_USER.接下来我尝试的是提供 AbstractUserDetailsAuthenticationProvider 的自定义实现:

Everything worked (I mean I was successfully authenticated) except that I still had only ROLE_USER. Next what I tried was providing a custom implementation of 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?) {
        }
    }
}

结果相同,只有 ROLE_USER 存在.

with same result, only the ROLE_USER was present.

我非常感谢你们的任何想法,如何在验证 access_token 并从身份验证服务器获取用户名后向 Authentication 对象添加一些角色.

I would really appreciate any ideas from you guys how add some roles to the Authentication object after the access_token was validated and username obtained from Auth server.

推荐答案

OP 的解决方案.

首先,我需要提供自定义的 PrincipalExtractorAuthoritiesExtractor 实现.但是要让 Spring 使用它们,在配置中必须不要使用 security.oauth2.resource.token-info-uri 而是 security.oauth2.resource.user-info-uri> 相反(我真的没想到这是我问题的根源之一).
最后,安全配置必须在 ResourceServerConfigurerAdapter 中完成,而不是在 WebSecurityConfigurerAdapter 中.

First of all I needed to provide custom PrincipalExtractor and AuthoritiesExtractor implementations. But to make Spring use them it is necessary in configuration NOT to use security.oauth2.resource.token-info-uri but security.oauth2.resource.user-info-uri instead (I really didn't expect this to be one of the roots of my problem).
Finally the security config must be done in ResourceServerConfigurerAdapter, not in 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)
    }

这篇关于Spring 在资源服务器上启动 OAuth2 自定义角色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆