我试图将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的问题)
不会生成令牌,请参阅下文了解更多信息。
请求:
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");
}
}
}
主要内容:从LOCAL存储引擎迁移到PLOCAL升级时,必须考虑版本号和格式。 有三种格式 - ,,。 版本需要不兼容的API更改。 版本需要向后兼容的功能。 版本需要向后兼容的错误修复。 要在小版本和主版本之间同步,可能需要导出和导入数据库。 有时需要将数据库从迁移到,并且需要将图形迁移到RidBag。 从LOCAL存储引擎迁移到PLOCAL 从版本开始OrientDB附带一个全新的存储引擎:PLOCAL(分页本地)。 它像LOCAL一样持久
讨论 Chromium 和 Node.js 都依赖于 V8 , Electron 只包含 了 V8 的一个副本,所以务必确保选择的 V8 版本与构建版本的 Node.js 和 Chromium 相兼容。 升级 Node 比升级 Chromium 容易得多,因此如果首先升级Chromium,然后升级 Node 版本至最接近 Chromiun 所包含的 V8 版本,出现的冲突可能会小一些。 Elect
本文概述了在Electron中升级Chromium所需的步骤。 将libcc升级到新的Chromium版本 使Electron兼容新的libcc 如有必要,请更新Electron的相关依赖(如崩溃报告,NodeJS等) 创建libcc和Electron的内部编译本 如有需要,请更新Electron文档 Upgrading Chromium This is an overview of the st
花点功夫去改善HTTP协议显然是极好的事情。我们可以着手于以下几个方面: 降低协议对延迟的敏感 修复pipelining和head of line blocking的问题 防止主机需求更高的连接数量 保留所有现有的接口,内容,URI格式和结构 由IETF的HTTPbis工作组来制定 4.1. IETF和HTTPbis工作组 The Internet Engineering Task Force (
我们在kubernetes1.6的时候同时安装了dashboard插件,该插件也是基于kubernetes1.6版本开发的。如今kubernetes1.8版本业已发布,如何升级dashboard以获取新版中功能呢? Dashboard的升级比较简单,因为它仅仅是一个前端应用,用来展现集群信息和与后端API交互,理论上只需要更新原先dashboard的yaml配置文件中的镜像就可以了,但是为了使用d
Ceph 的各个版本都可能有特定的步骤,升级前请参考与此版本相关的章节和发布说明文档,以确定有哪些特定于此版本的步骤。 概述 你可以在 Ceph 集群在线且提供服务时升级守护进程!某些类型的守护进程依赖其他的,如 Ceph 元数据服务器和 Ceph 对象网关依赖于 Ceph 监视器和 OSD 守护进程,所以我们建议按以下顺序升级: ceph-deploy 工具 Ceph 监视器 Ceph OSD
IMPORTANT: 在升级 Kibana 之前: 请参考重要变更文档。 在升级生产服务之前请先在测试环境测试升级。 使用 Elasticsearch 的 snapshots 特性备份数据。除非存在备份数据,否则版本 不能向前回滚 。 如果使用了自定义插件,检查其是否有兼容版本。 从不同的 Kibana 版本进行升级,过程也不相同。请参考以下表格决定需要按照哪个过程进行升级: 当前版本 目标版本
本文介绍了如何修改 Android 项目来从 旧版的 Cordova 升级。大部分指令适用于与旧的 cordova CLI 工具创建的项目。有关 CLI 内容,可以参阅命令行界面(CLI) 升级至 4.0.0 升级至 4.0.0 有些特殊的步骤,首先, 对于非 CLI 项目,运行: bin/update path/to/project 对于 CLI 项目: 升级 cordova CLI