我正在尝试将
Spring安全性OAuth2配置从2.0.0.RC1升级到2.0.3.RELEASE.当时我从sprklr示例中复制了配置并使其正常工作.所以它基于基于xml的Spring Security OAuth2配置的工作示例.
现在,我已经升级到Spring Security最新版本(在撰写本文时为2.0.3)并且还尝试将其转换为java配置.我发布了xml配置和下面的java配置.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd"> <!-- Authentication manager. --> <security:authentication-manager alias="authenticationManager"> <security:authentication-provider> <security:jdbc-user-service data-source-ref="dataSource" users-by-username-query="select a.username,a.password,a.enabled,a.email from account a where a.username = ?" authorities-by-username-query="select a.username,r.role_name from account a,role r,account_role ar where a.id = ar.account_id and r.id = ar.role_id and a.username = ?" /> <security:password-encoder ref="passwordEncoder"/> </security:authentication-provider> </security:authentication-manager> <security:global-method-security secured-annotations="enabled" jsr250-annotations="enabled" pre-post-annotations="enabled" /> <security:http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager"> <security:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" /> <security:anonymous enabled="false" /> <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" /> <!-- include this only if you need to authenticate clients via request parameters --> <security:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" /> <security:access-denied-handler ref="oauthAccessDeniedHandler" /> </security:http> <security:http pattern="/api/.*/accounts" request-matcher="regex" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" use-expressions="true"> <security:intercept-url pattern="/api/.*/accounts" method="POST" requires-channel="https" access="#oauth2.clientHasRole('ROLE_CLIENT') or hasRole('ROLE_ANONYMOUS')"/> <security:intercept-url pattern="/.*" access="denyAll()" /> <security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> <security:access-denied-handler ref="oauthAccessDeniedHandler" /> <security:expression-handler ref="oauthWebExpressionHandler" /> </security:http> <security:http pattern="/api/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager"> <security:anonymous enabled="false" /> <security:intercept-url pattern="/api/**" access="ROLE_USER,SCOPE_TRUST,SCOPE_PLAY"/> <security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> <security:access-denied-handler ref="oauthAccessDeniedHandler" /> </security:http> <bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> <property name="realmName" value="*****" /> </bean> <bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> <property name="realmName" value="*****/client" /> <property name="typeName" value="Basic" /> </bean> <bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" /> <bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter"> <property name="authenticationManager" ref="clientAuthenticationManager" /> </bean> <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"> <constructor-arg> <list> <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" /> <bean class="org.springframework.security.access.vote.RoleVoter" /> <bean class="org.springframework.security.access.vote.AuthenticatedVoter" /> </list> </constructor-arg> </bean> <security:authentication-manager id="clientAuthenticationManager"> <security:authentication-provider user-service-ref="clientDetailsUserService" /> </security:authentication-manager> <bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService"> <constructor-arg ref="clientDetails" /> </bean> <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" /> <bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices"> <property name="tokenStore" ref="tokenStore" /> <property name="tokenEnhancer" ref="tokenEnhancer" /> <property name="supportRefreshToken" value="true" /> <property name="clientDetailsService" ref="clientDetails" /> <property name="accessTokenValiditySeconds" value="6000" /> </bean> <bean id="tokenEnhancer" class="com.****.*****.config.*****TokenEnhancer" /> <bean id="requestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory"> <constructor-arg name="clientDetailsService" ref="clientDetails" /> </bean> <bean id="userApprovalHandler" class="com.****.*****.config.*****UserApprovalHandler"> <property name="approvalStore" ref="approvalStore" /> <property name="clientDetailsService" ref="clientDetails" /> <property name="requestFactory" ref="requestFactory" /> </bean> <bean id="approvalStore" class="org.springframework.security.oauth2.provider.approval.TokenApprovalStore"> <property name="tokenStore" ref="tokenStore" /> </bean> <oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler"> <oauth:authorization-code /> <oauth:implicit /> <oauth:refresh-token /> <oauth:client-credentials /> <oauth:password /> </oauth:authorization-server> <oauth:resource-server id="resourceServerFilter" resource-id="*****" token-services-ref="tokenServices" /> <oauth:client-details-service id="clientDetails"> <oauth:client client-id="*****-PHP-demo" secret="??????????" authorized-grant-types="password,authorization_code,refresh_token,client_credentials" authorities="ROLE_USER,ROLE_CLIENT" scope="play,trust" access-token-validity="6000"/> <oauth:client client-id="*****-swagger-ui" authorized-grant-types="implicit" authorities="ROLE_USER,ROLE_CLIENT,ROLE_TRUSTED_CLIENT" scope="play,trust" redirect-uri="${baseUrl}/o2c.html" autoapprove="true" access-token-validity="6000"/> <oauth:client client-id="*****-runscope" secret="???????????????????????????????" authorized-grant-types="password,refresh_token" authorities="ROLE_USER,trust" redirect-uri="https://www.runscope.com/oauth_tool/callback" autoapprove="true" access-token-validity="6000"/> </oauth:client-details-service> <oauth:expression-handler id="oauthExpressionHandler" /> <oauth:web-expression-handler id="oauthWebExpressionHandler" />
和java配置(到目前为止..)
@Configuration public class SecurityConfig { @Autowired private DataSource dataSource; @Value("${baseUrl}") private String baseUrl; @Bean public ClientDetailsService clientDetailsService() throws Exception { ClientDetailsServiceConfiguration serviceConfig = new ClientDetailsServiceConfiguration(); serviceConfig.clientDetailsServiceConfigurer().inMemory() .withClient("*****-????????") .secret("????????????????????") .authorizedGrantTypes("password","authorization_code","refresh_token","client_credentials") .authorities("ROLE_CLIENT","ROLE_TRUSTED_CLIENT") .scopes("play","trust") .and() .withClient("*****-????????") .authorizedGrantTypes("implicit") .authorities("ROLE_USER","ROLE_CLIENT","trust") .redirectUris(baseUrl + "/o2c.html") .autoApprove(true) .and() .withClient("*****-???????") .secret("????????????????????") .authorizedGrantTypes("password","refresh_token") .authorities("ROLE_USER","trust") .redirectUris("https://www.runscope.com/oauth_tool/callback") .autoApprove(true); return serviceConfig.clientDetailsService(); } @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } @Bean public DefaultTokenServices tokenServices() throws Exception { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setAccessTokenValiditySeconds(6000); tokenServices.setClientDetailsService(clientDetailsService()); tokenServices.setTokenEnhancer(new *****TokenEnhancer()); tokenServices.setSupportRefreshToken(true); tokenServices.setTokenStore(tokenStore()); return tokenServices; } @Bean public UserApprovalHandler userApprovalHandler() throws Exception { *****UserApprovalHandler handler = new *****UserApprovalHandler(); handler.setApprovalStore(approvalStore()); handler.setClientDetailsService(clientDetailsService()); handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService())); return handler; } @Bean public ApprovalStore approvalStore() { TokenApprovalStore store = new TokenApprovalStore(); store.setTokenStore(tokenStore()); return store; } @Bean public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler() { return new OAuth2AccessDeniedHandler(); } @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) @EnableWebSecurity protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private DataSource dataSource; @Resource private PasswordEncoder passwordEncoder; @Autowired private ClientDetailsService clientDetailsService; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Bean protected UserDetailsService clientDetailsUserService() { return new ClientDetailsUserDetailsService(clientDetailsService); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(clientDetailsUserService()); JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcUserDetail = new JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder>(); jdbcUserDetail.dataSource(dataSource); jdbcUserDetail.passwordEncoder(passwordEncoder); jdbcUserDetail.authoritiesByUsernameQuery("select a.username,account_role ar where a.id = ar.account_id and r.id = ar.role_id and a.username = ?"); jdbcUserDetail.usersByUsernameQuery("select a.username,a.email from account a where a.username = ?"); auth.apply(jdbcUserDetail); } @Bean(name="authenticationManager") @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean protected AuthenticationEntryPoint authenticationEntryPoint() { OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); entryPoint.setTypeName("Basic"); entryPoint.setRealmName("oauth2/client"); return entryPoint; } @Override public void configure(WebSecurity webSecurity) throws Exception { webSecurity .ignoring() .antMatchers("/index.html","/resources/**","/swagger/**","/copyright*","/api-docs/**") .and() .debug(true); } @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.anonymous().disable() .antMatcher("/oauth/token") .authorizeRequests().anyRequest().authenticated() .and() .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) .and() .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable() .exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler) .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // @formatter:on } } @Configuration @EnableResourceServer protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Autowired private ResourceServerTokenServices tokenServices; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.tokenServices(tokenServices); resources.resourceId("*****"); } @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off http .anonymous() .disable(); // API calls http .authorizeRequests() .regexMatchers(HttpMethod.POST,"/api/.*/accounts") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // API calls http .authorizeRequests() .antMatchers("/api/**") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // @formatter:on } } @Configuration @EnableAuthorizationServer protected static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private DefaultTokenServices tokenServices; @Autowired private ClientDetailsService clientDetailsService; @Autowired private UserApprovalHandler userApprovalHandler; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.clientDetailsService(clientDetailsService) .tokenServices(tokenServices) .userApprovalHandler(userApprovalHandler); } } }
添加更多信息(根据Dave Syer的问题)
不生成令牌,请参阅下面的更多信息.
请求:
curl -k -i -H "Accept: application/json" -X POST -d "grant_type=password&client_id=*****-PHP-demo&client_secret=???????&scope=play trust&username=tester&password=121212" https://localhost:8443/*****/oauth/token
响应:
HTTP/1.1 401 Unauthorized Server: Apache-Coyote/1.1 X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Cache-Control: no-cache,no-store,max-age=0,must-revalidate Pragma: no-cache Expires: 0 Strict-Transport-Security: max-age=31536000 ; includeSubDomains X-Frame-Options: DENY Cache-Control: no-store Pragma: no-cache WWW-Authenticate: Basic realm="*****/client",error="unauthorized",error_description="An Authentication object was not found in the SecurityContext" Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Tue,16 Sep 2014 14:05:19 GMT
{“error”:“unauthorized”,“error_description”:“在SecurityContext中找不到身份验证对象”}
服务器日志:
Request received for POST '/oauth/token': org.apache.catalina.connector.RequestFacade@344dad0c servletPath: pathInfo:/oauth/token headers: user-agent: curl/7.30.0 host: localhost:8443 accept: application/json content-length: 145 content-type: application/x-www-form-urlencoded Security filter chain: [ WebAsyncManagerIntegrationFilter SecurityContextPersistenceFilter HeaderWriterFilter logoutFilter BasicAuthenticationFilter RequestCacheAwareFilter SecurityContextHolderAwareRequestFilter SessionManagementFilter ExceptionTranslationFilter FilterSecurityInterceptor ]
(10月14日更新)
Java安全配置;
@Configuration public class SecurityConfig { @Autowired private DataSource dataSource; @Value("${baseUrl}") private String baseUrl; @Bean public ClientDetailsService clientDetailsService() throws Exception { ClientDetailsServiceConfiguration serviceConfig = new ClientDetailsServiceConfiguration(); serviceConfig.clientDetailsServiceConfigurer().inMemory() .withClient("abc") .secret("?????") .authorizedGrantTypes("password","client_credentials") .authorities("ROLE_CLIENT","ROLE_TRUSTED_CLIENT") .scopes("play","trust") .and() .withClient("xyz") .authorizedGrantTypes("implicit") .authorities("ROLE_USER","trust") .redirectUris(baseUrl + "/o2c.html") .autoApprove(true) .and() .withClient("zzz") .secret("?????????????????") .authorizedGrantTypes("password","refresh_token") .authorities("ROLE_USER","trust") .redirectUris("https://www.runscope.com/oauth_tool/callback") .autoApprove(true); return serviceConfig.clientDetailsService(); } @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } @Bean public DefaultTokenServices tokenServices() throws Exception { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setAccessTokenValiditySeconds(6000); tokenServices.setClientDetailsService(clientDetailsService()); tokenServices.setTokenEnhancer(new MyTokenEnhancer()); tokenServices.setSupportRefreshToken(true); tokenServices.setTokenStore(tokenStore()); return tokenServices; } @Bean public UserApprovalHandler userApprovalHandler() throws Exception { MyUserApprovalHandler handler = new MyUserApprovalHandler(); handler.setApprovalStore(approvalStore()); handler.setClientDetailsService(clientDetailsService()); handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService())); return handler; } @Bean public ApprovalStore approvalStore() { TokenApprovalStore store = new TokenApprovalStore(); store.setTokenStore(tokenStore()); return store; } @Bean public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler() { return new OAuth2AccessDeniedHandler(); } @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) @EnableWebSecurity protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private DataSource dataSource; @Resource private PasswordEncoder passwordEncoder; @Autowired private ClientDetailsService clientDetailsService; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Bean protected UserDetailsService clientDetailsUserService() { return new ClientDetailsUserDetailsService(clientDetailsService); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcUserDetail = new JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder>(); jdbcUserDetail.dataSource(dataSource); jdbcUserDetail.passwordEncoder(passwordEncoder); jdbcUserDetail.authoritiesByUsernameQuery("select a.username,account_role ar where a.id = ar.account_id and r.id = ar.role_id and a.username = ?"); jdbcUserDetail.usersByUsernameQuery("select a.username,a.email from account a where a.username = ?"); auth.apply(jdbcUserDetail); } @Bean(name="authenticationManager") @Override public AuthenticationManager authenticationManagerBean() throws Exception { AuthenticationManager am = super.authenticationManagerBean(); return am; } @Bean protected AuthenticationEntryPoint authenticationEntryPoint() { OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); entryPoint.setTypeName("Basic"); entryPoint.setRealmName("redrum/client"); return entryPoint; } @Override public void configure(WebSecurity webSecurity) throws Exception { webSecurity .ignoring() .antMatchers("/resources/**","/api-docs/**") .and() .debug(true); } @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.anonymous().disable() .antMatcher("/oauth/token") .authorizeRequests().anyRequest().authenticated() .and() .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) .and() .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable() .exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler) .and() .addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // @formatter:on } @Bean public ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() throws Exception { ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter(); filter.setAuthenticationEntryPoint(authenticationEntryPoint()); filter.setAuthenticationManager(authenticationManagerBean()); return filter; } } @Configuration @EnableResourceServer protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Autowired private ResourceServerTokenServices tokenServices; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Autowired private AuthenticationManager authenticationManager; @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.tokenServices(tokenServices); resources.resourceId("xyz"); } @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off http .anonymous() .disable(); // API calls http .authorizeRequests() .regexMatchers(HttpMethod.POST,"/api/.*/accounts") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // API calls http .authorizeRequests() .antMatchers("/api/**") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // @formatter:on } } @Configuration @EnableAuthorizationServer protected static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private DefaultTokenServices tokenServices; @Autowired private ClientDetailsService clientDetailsService; @Autowired private UserApprovalHandler userApprovalHandler; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.clientDetailsService(clientDetailsService) .tokenServices(tokenServices) .userApprovalHandler(userApprovalHandler); } } }
解决方法
这是解决方案;希望它对某人有用.使用Spring OAuth2文档和示例的当前状态来确定这个解决方案并不容易.
@Configuration public class SecurityConfig { @Autowired private DataSource dataSource; @Autowired private ClientDetailsService clientDetailsService; @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } @Bean public DefaultTokenServices tokenServices() throws Exception { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setAccessTokenValiditySeconds(6000); tokenServices.setClientDetailsService(clientDetailsService); tokenServices.setTokenEnhancer(new MyTokenEnhancer()); tokenServices.setSupportRefreshToken(true); tokenServices.setTokenStore(tokenStore()); return tokenServices; } @Bean public UserApprovalHandler userApprovalHandler() throws Exception { MyUserApprovalHandler handler = new MyUserApprovalHandler(); handler.setApprovalStore(approvalStore()); handler.setClientDetailsService(clientDetailsService); handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); handler.setUseApprovalStore(true); return handler; } @Bean public ApprovalStore approvalStore() { TokenApprovalStore store = new TokenApprovalStore(); store.setTokenStore(tokenStore()); return store; } @Bean public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler() { return new OAuth2AccessDeniedHandler(); } @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) @EnableWebSecurity protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Value("${baseUrl}") private String baseUrl; @Autowired private DataSource dataSource; @Resource private PasswordEncoder passwordEncoder; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Bean public ClientDetailsService clientDetailsService() throws Exception { ClientDetailsServiceConfiguration serviceConfig = new ClientDetailsServiceConfiguration(); serviceConfig.clientDetailsServiceConfigurer().inMemory() .withClient("***-***-****") .secret("???????????????????????????????") .authorizedGrantTypes("password","trust") .and() .withClient("***-******-**") .authorizedGrantTypes("implicit") .authorities("ROLE_USER","trust") .redirectUris(baseUrl + "/o2c.html") .autoApprove(true) .and() .withClient("******-***********") .secret("???????????????????????????????????") .authorizedGrantTypes("password","trust") .redirectUris("https://www.runscope.com/oauth_tool/callback") .autoApprove(true); return serviceConfig.clientDetailsService(); } @Bean UserDetailsService clientDetailsUserDetailsService() throws Exception { return new ClientDetailsUserDetailsService(clientDetailsService()); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcUserDetail = new JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder>(); jdbcUserDetail.dataSource(dataSource); jdbcUserDetail.passwordEncoder(passwordEncoder); jdbcUserDetail.authoritiesByUsernameQuery("select a.username,a.email from account a where a.username = ?"); auth.apply(jdbcUserDetail); auth.userDetailsService(clientDetailsUserDetailsService()); } @Bean(name="authenticationManager") @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean protected AuthenticationEntryPoint authenticationEntryPoint() { OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); entryPoint.setTypeName("Basic"); entryPoint.setRealmName("app/client"); return entryPoint; } @Override public void configure(WebSecurity webSecurity) throws Exception { webSecurity .ignoring() .antMatchers("/resources/**","/api-docs/**") .and() .debug(true); } @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.anonymous().disable() .antMatcher("/oauth/token") .authorizeRequests().anyRequest().authenticated() .and() .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) .and() .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable() .exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler) .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // @formatter:on ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter(); filter.setAuthenticationManager(authenticationManagerBean()); filter.afterPropertiesSet(); http.addFilterBefore(filter,BasicAuthenticationFilter.class); } } @Configuration @EnableResourceServer protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Autowired private ResourceServerTokenServices tokenServices; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { //resources.tokenServices(tokenServices); resources.resourceId("app"); } @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off http .anonymous() .disable(); // API calls http .authorizeRequests() .regexMatchers(HttpMethod.POST,"/api/.*/accounts") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // API calls http .authorizeRequests() .antMatchers("/api/**") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // @formatter:on } } @Configuration @EnableAuthorizationServer protected static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private DefaultTokenServices tokenServices; @Autowired private ClientDetailsService clientDetailsService; @Autowired private UserApprovalHandler userApprovalHandler; @Autowired private AuthenticationManager authenticationManager; @Autowired AuthenticationEntryPoint authenticationEntryPoint; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .tokenServices(tokenServices) .userApprovalHandler(userApprovalHandler) .authenticationManager(authenticationManager); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.withClientDetails(clientDetailsService); } @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.authenticationEntryPoint(authenticationEntryPoint) .realm("app/clients"); } } }