我正在尝试使用Spring Security OAuth2和JWT实现单点登录 . 我使用两个单独的应用程序
授权服务器 - 这是中央身份验证机制
客户端应用程序:使用SSO的应用程序
当用户尝试访问客户端应用程序中的安全页面时,他们将通过身份验证服务器重定向到首先进行身份验证 .
我正在使用OAuth2中的授权代码授权类型来驱动身份验证委派 .
Authorization server:
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
public static final Logger LOGGER = LoggerFactory.getLogger(AuthorizationServerConfigurerAdapter.class);
@Autowired
private AuthenticationManager authenticationManager;
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("abcd");
return converter;
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setTokenEnhancer(accessTokenConverter());
return defaultTokenServices;
}
@Override
public void configure(ClientDetailsServiceConfigurer clientDetailsServiceConfigurer) throws Exception {
clientDetailsServiceConfigurer
.inMemory()
.withClient("webapp")
.secret("Pass")
.authorizedGrantTypes("implicit", "refresh_token", "password", "authorization_code")
.scopes("user_info")
.autoApprove(true);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager);
}
}
授权服务器上的安全配置
@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Value("${ldap.url}")
private String ldapUrl;
@Value("${ldap.userDnPatterns}")
private String ldapUserDnPatterns;
@Autowired
private PersonService personService;
@Autowired
private RoleService roleService;
@Override
protected void configure(HttpSecurity http) throws Exception { // @formatter:off
http.requestMatchers()
.antMatchers("/login", "/oauth/authorize")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll();
} // @formatter:on
@Bean(name = "authenticationManager")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(this.ldapAndDatabaseAuthenticationProvider());
}
@Bean(name="ldapAuthenticationProvider")
public AuthenticationProvider ldapAndDatabaseAuthenticationProvider(){
LdapUserDetailsMapper userDetailsMapper = new LdapUserDetailsMapper();
userDetailsMapper.setRoleAttributes(new String[]{"groupMembership"});
LdapAndDatabaseAuthenticationProvider provider =
new LdapAndDatabaseAuthenticationProvider(
this.ldapAuthenticator(),
this.ldapAuthoritiesPopulator(),
this.personService);
provider.setUserDetailsContextMapper(userDetailsMapper);
return provider;
}
@Bean( name = "ldapAuthoritiesPopulator" )
public LdapAndDatabaseAuthoritiesPopulator ldapAuthoritiesPopulator(){
return new LdapAndDatabaseAuthoritiesPopulator(this.contextSource(), "", roleService);
}
@Bean( name = "ldapAuthenticator" )
public LdapAuthenticator ldapAuthenticator() {
BindAuthenticator authenticator = new BindAuthenticator( this.contextSource() );
authenticator.setUserDnPatterns(new String[]{"cn={0},ou=prod,o=TEMP"});
return authenticator;
}
@Bean( name = "contextSource" )
public DefaultSpringSecurityContextSource contextSource() {
DefaultSpringSecurityContextSource contextSource =
new DefaultSpringSecurityContextSource( ldapUrl );
return contextSource;
}
}
application.properties:
server.port=8888
server.context-path=/auth
security.basic.enabled=false
当我登录客户端应用程序时,它正确转发到授权服务器进行单点登录 . 我输入用户凭据 . 用户成功通过身份验证,但我在浏览器上看到以下错误:
OAuth错误错误=“invalid_grant”,error_description =“redirect_uri只能由implicit或authorization_code授权类型使用 . ”
我还在日志中看到以下内容:
02:14:43.610 [http-nio-8888-exec-6] DEBUG o.s.s.o.p.e.FrameworkEndpointHandlerMapping/getHandlerInternal Looking up handler method for path /oauth/authorize
02:14:43.614 [http-nio-8888-exec-6] DEBUG o.s.s.o.p.e.FrameworkEndpointHandlerMapping/getHandlerInternal Returning handler method [public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(java.util.Map<java.lang.String, java.lang.Object>,java.util.Map<java.lang.String, java.lang.Str ing>,org.springframework.web.bind.support.SessionStatus,java.security.Principal)]
02:14:43.849 [http-nio-8888-exec-6] INFO o.s.s.o.p.e.AuthorizationEndpoint/handleOAuth2Exception Handling OAuth2 error: error="invalid_grant", error_description="A redirect_uri can only be used by implicit or authorization_code grant types."
你能帮我找到问题吗?
UPDATE 实际上,杜尔是对的 . 这种配置是正确的,并且工作正常 . 我有另一个配置文件来配置JdbcClientDetails,它覆盖了在此配置中使用inmemory创建的clientDetailsService .