【问题标题】:How to use RemoteTokenService?如何使用远程令牌服务?
【发布时间】:2023-04-01 11:58:01
【问题描述】:

我有一个使用 Spring-Security-oauth2 构建的单独 ResourceServer。这是 RemoteTokenService 的代码。

@Bean
public ResourceServerTokenServices tokenService() {
   RemoteTokenServices tokenServices = new RemoteTokenServices();
   tokenServices.setClientId("sample_test_client_app");
   tokenServices.setClientSecret("secret");
   tokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
   return tokenServices;
}

当我使用 AccessToken 访问资源服务器时,我得到以下信息:

FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /oauth/check_token; Attributes: [denyAll()]
FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@c3f3b25: Principal: org.springframework.security.core.userdetails.User@3c0cd8e: Username: sample_test_client_app; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities
AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@6172e10, returned: -1
ExceptionTranslationFilter - Access is denied (user is not anonymous); delegating to AccessDeniedHandler

谁能告诉我我的配置有什么问题?

更新: 我的 Spring 安全配置。

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.inMemoryAuthentication().withUser("developer").password("developer").roles("USER");

    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/webjars/**", "/images/**", "/oauth/uncache_approvals", "/oauth/cache_approvals");
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
                 http
            .authorizeRequests().antMatchers("/login.jsp").permitAll().and()
            .authorizeRequests().antMatchers("/oauth/check_token").permitAll().and()
            .authorizeRequests()
                .anyRequest().hasRole("USER")
                .and()
            .exceptionHandling()
                .accessDeniedPage("/login.jsp?authorization_error=true")
                .and()
            .logout()
                .logoutSuccessUrl("/index.jsp")
                .logoutUrl("/logout.do")
                .and()
            .formLogin();
        // @formatter:on
    }
}

我的身份验证服务器配置。

@Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

        @Autowired
        private TokenStore tokenStore;

        @Autowired
        private UserApprovalHandler userApprovalHandler;

        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            // @formatter:off
            clients
                .inMemory()
                .withClient("sample_test_client_app")
                .secret("secret")
                .authorizedGrantTypes("client_credentials","authorization_code")
                .authorities("ROLE_CLIENT")
                .resourceIds(CHANAKYA_RESOURCE_ID)
                .scopes("read","write");

            // @formatter:on
        }

        @Bean
        public TokenStore tokenStore() {
            return new InMemoryTokenStore();
        }

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
                    .authenticationManager(authenticationManager);
        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            oauthServer.realm("resource_server/client");
        }

    }

【问题讨论】:

  • 您的 /check_token 似乎使用 denyAll() 保护。这可能是一个错误,但为了能够纠正它,您必须显示破坏它的代码。
  • 非常感谢这个问题,我花了几个小时才找到合适的解决方案:)

标签: spring spring-security oauth-2.0 access-token spring-security-oauth2


【解决方案1】:

我有以下配置:

@Configuration
@EnableWebSecurity
@EnableAuthorizationServer
public class OAuthSecurityConfig extends AuthorizationServerConfigurerAdapter {
// ...
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        // (!)
        oauthServer.allowFormAuthenticationForClients();
    }
// ...

我添加了以下行:

    oauthServer.checkTokenAccess("permitAll()");

进入带有“(!)”的行来解决同样的问题。

【讨论】:

  • 这将是关键(我猜默认情况下它是关闭的)。我想建议“permitAll()”可能有点过于宽松。但这真的是你的选择。
  • @DaveSyer 同意。但这只是示例;)
  • @DaveSyer 是的,默认情况下它是关闭的。
  • @Alex 这对我有用。但是你能告诉我如何在资源服务器上获取 ClientDetails 以便我可以检查客户端的角色以确保安全。
  • 我还在等你的回答@DaveSyer。
【解决方案2】:

在资源服务器上,我有一个安全的 url,例如仅当“客户端”应用程序具有角色“ROLE_CLIENT”时才访问的“数据/用户”。在这里,我正在使用 RemoteTokenService,并且我在 oauth 服务器上配置了一个客户端,其角色为“ROLE_CLIENT”和 client_credential 授权。我的客户端如何访问此 url ???

所有请求都应包含“Bearer”类型的授权和令牌:

> curl "https://localhost:8080/users/me" -H "Pragma: no-cache" -H "Origin:
> http://localhost:8080" -H "Accept-Encoding: gzip,deflate" -H
> "Accept-Language: en-US,en;q=0.8,es;q=0.6" -H "Authorization: Bearer
> f07abd25-af1f-44e2-XXXX-ba5071168XXX" -H "Accept: */*" -H
> "Cache-Control: no-cache" -H "User-Agent: Mozilla/5.0 (Windows NT 6.1;
> WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124
> Safari/537.36" -H "Connection: keep-alive" -H "Referer:
> http://localhost:8080/test.html" --compressed

当我使用 RemoteTokenService 时,我的令牌将通过 “/oauth/check_token”(CheckTokenEndpoint)。不给任何 有关客户角色的信息。那么如何比较客户的角色。

Spring 安全性具有所有必需的信息。您需要做的就是保护您的端点。就我而言:

@PreAuthorize("hasAnyAuthority('USER_READ')")

在这种情况下,只有角色为“USER_READ”的用户才能访问我的端点。


如有任何其他问题,请随时提出。

【讨论】:

  • 感谢您的回答。正如您所说“在这种情况下,只有角色为 'USER_ROLE' 的用户才能访问我的端点”。在 Client_credential 授予用户不存在。它仅与客户端有关。在这种情况下,当资源服务器请求授权服务器进行令牌认证时,外部服务器仅返回 client_id 、令牌过期时间和该客户端的范围。所以在那种情况下我该如何检查 hasAuthority ???
  • @prtk_shah 正确,客户端信息仅包含此类信息pastie.org/9634116,但令牌信息包含更多信息pastie.org/9634123
  • 感谢您。但我对你的回答有点困惑。您能否更详细地向我解释一下,如何在使用 RemoteTokenService 和 ClientCredential 授权时获得 ClientAuthority。你从哪里得到上面的 JSON?
  • @prtk_shah 抱歉,我暂时不知道。可能我在某些方面错了......我今天会检查它并让你知道。关于您的第二个问题:我实现了 TokenStore 以在 MongoDB 中存储令牌。
  • @prtk_shah 我在日志中找到了以下行,它可能是您问题的答案:'27789 [http-bio-8081-exec-1] DEBUG org.springframework.security.web。 context.HttpSessionSecurityContextRepository - SecurityContext 存储到 HttpSession: 'org.springframework.security.core.context.SecurityContextImpl@cba196e7: Authentication: org.springframework.security.oauth2.provider.OAuth2Authentication@cba196e7: Principal: ;凭证:[受保护];已认证:真实;详细信息:remoteAddress=127.0.0.1,tokenValue=;授予权限:USER_READ'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
  • 2021-04-26
  • 1970-01-01
  • 2020-10-06
  • 2020-03-19
  • 1970-01-01
相关资源
最近更新 更多