我正在尝试将 Spring security 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,authorization_code,refresh_token"
authorities="ROLE_USER, ROLE_CLIENT, ROLE_TRUSTED_CLIENT"
scope="play,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", "ROLE_TRUSTED_CLIENT")
.scopes("play", "trust")
.redirectUris(baseUrl + "/o2c.html")
.autoApprove(true)
.and()
.withClient("*****-???????")
.secret("????????????????????")
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.authorities("ROLE_USER", "ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("play", "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, 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 = ?");
jdbcUserDetail.usersByUsernameQuery("select a.username, a.password, a.enabled, 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 的问题)
不生成 token ,请参阅下文了解更多信息。
要求:
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", "authorization_code", "refresh_token", "client_credentials")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("play", "trust")
.and()
.withClient("xyz")
.authorizedGrantTypes("implicit")
.authorities("ROLE_USER", "ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("play", "trust")
.redirectUris(baseUrl + "/o2c.html")
.autoApprove(true)
.and()
.withClient("zzz")
.secret("?????????????????")
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.authorities("ROLE_USER", "ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("play", "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, 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 = ?");
jdbcUserDetail.usersByUsernameQuery("select a.username, a.password, a.enabled, 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/**", "/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()
.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", "authorization_code", "refresh_token", "client_credentials")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("play", "trust")
.and()
.withClient("***-******-**")
.authorizedGrantTypes("implicit")
.authorities("ROLE_USER", "ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("play", "trust")
.redirectUris(baseUrl + "/o2c.html")
.autoApprove(true)
.and()
.withClient("******-***********")
.secret("???????????????????????????????????")
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.authorities("ROLE_USER", "ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("play", "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, 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 = ?");
jdbcUserDetail.usersByUsernameQuery("select a.username, a.password, a.enabled, 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/**", "/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
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");
}
}
}
关于java - 升级 Spring Security OAuth2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25860198/
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我最近决定从我的系统中卸载RVM。在thispage提出的一些论点说服我:实际上,我的决定是,我根本不想担心Ruby的多个版本。我只想使用1.9.2-p290版本而不用担心其他任何事情。但是,当我在我的Mac上运行ruby--version时,它告诉我我的版本是1.8.7。我四处寻找如何简单地从我的Mac上卸载这个Ruby,但奇怪的是我没有找到任何东西。似乎唯一想卸载Ruby的人运行linux,而使用Mac的每个人都推荐RVM。如何从我的Mac上卸载Ruby1.8.7?我想升级到1.9.2-p290版本,并且我希望我的系统上只有一个版本。 最佳答案
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候