在过去的几天里,我一直在使用spring-security-oauth2来实现spring boot/spring security /和java配置.我已经设法解决了大部分困难,但我对现在出了什么问题感到难过.
我正在成功完成以下步骤:
将用户发送给提供商以授权应用程序代表他们行事
系统会提示用户按安全性登录提供程序
用户授权应用程序,重定向URL将它们发送回原始URL的客户端应用程序以及?code=asdfa&state=asdfasf
查询字符串
此时,我相信无论使用什么,都AuthorizationCodeResourceDetails
应该为访问令牌交换授权代码和客户端应用凭证.这是进程因以下堆栈跟踪而失败的地方.
Caused by: org.springframework.security.oauth2.common.exceptions.InvalidRequestException: Possible CSRF detected - state parameter was present but no state could be found at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.getParametersForTokenRequest(AuthorizationCodeAccessTokenProvider.java:246) at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:198) at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:142) at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:118) at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221) at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173) at org.springframework.security.oauth2.client.OAuth2RestTemplate.createRequest(OAuth2RestTemplate.java:105) at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:564) at org.springframework.security.oauth2.client.OAuth2RestTemplate.doExecute(OAuth2RestTemplate.java:128) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:529) at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:261) at com.pvr.apps.admin.user.UserServiceImpl.getAllUsers(UserServiceImpl.java:51) at com.pvr.apps.admin.web.IndexController.serveUserList(IndexController.java:35)
客户端上的东西看起来像(我@EnableOAuth2Client
在主配置上也有一个注释).
@Component public class UserServiceImpl implements UserService { @Resource @Qualifier("accessTokenRequest") private AccessTokenRequest accessTokenRequest; public OAuth2ProtectedResourceDetails createResource() { AuthorizationCodeResourceDetails resourceDetails = new AuthorizationCodeResourceDetails(); resourceDetails.setScope(Lists.newArrayList("read", "write")); resourceDetails.setClientId("admin"); resourceDetails.setClientSecret("password"); resourceDetails.setAuthenticationScheme(AuthenticationScheme.query); resourceDetails.setAccessTokenUri("http://provider.com:8080/oauth/token"); resourceDetails.setUserAuthorizationUri("http://provider.com:8080/oauth/authorize"); return resourceDetails; } @Override public ListgetAllUsers() { RestTemplate template = new OAuth2RestTemplate(createResource(), new DefaultOAuth2ClientContext(accessTokenRequest)); ResponseEntity responseEntity = template.getForEntity("http://provider.com:8080/users/", User[].class); return Lists.newArrayList(responseEntity.getBody()); } }
在提供商方面:
授权服务器配置:
@Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{ @Autowired private LoginUrlAuthenticationEntryPoint authenticationEntryPoint; @Autowired private AuthenticationManager authenticationManager; @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer .authenticationEntryPoint(authenticationEntryPoint) .tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')") .checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')"); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); endpoints .authenticationManager(authenticationManager) .accessTokenConverter(converter) .tokenStore(new JwtTokenStore(converter)); } // TODO: this should read from a db public void configure(ClientDetailsServiceConfigurer clientConfigurer) throws Exception { clientConfigurer.inMemory() .withClient("admin").secret("password") .authorizedGrantTypes( GrantType.PASSWORD.type, GrantType.AUTHORIZATION_CODE.type, GrantType.IMPLICIT.type, GrantType.REFRESH_TOKEN.type ) .authorities("ROLE_TRUSTED_CLIENT") .scopes("read", "write", "trust") .accessTokenValiditySeconds(60); } }
和资源服务器配置:
@Configuration @EnableWebMvcSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class MySecurityConfig extends WebSecurityConfigurerAdapter { @Autowired UserDetailsService userDetailService; @Autowired AuthenticationProvider authenticationProvider; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(authenticationProvider); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginProcessingUrl("/login.do") .usernameParameter("uid") .passwordParameter("pwd") .loginPage("/login") .failureUrl("/login?error=true") .and() .userDetailsService(userDetailService); } }
Dave Syer.. 5
它正在寻找的状态将在,OAuth2ClientContext
但由于你刚刚创建了一个新的,它在需要时超出了范围.如果你注入一个来自@EnableOAuth2Client
它的那个,@Scope("session")
那么它将会在那里,它将能够为你解决状态.GitHub中的所有样本都以这种方式工作.或者你可以自己管理持久性,我想.
它正在寻找的状态将在,OAuth2ClientContext
但由于你刚刚创建了一个新的,它在需要时超出了范围.如果你注入一个来自@EnableOAuth2Client
它的那个,@Scope("session")
那么它将会在那里,它将能够为你解决状态.GitHub中的所有样本都以这种方式工作.或者你可以自己管理持久性,我想.