草庐IT

java - 升级 Spring Security OAuth2

coder 2024-03-27 原文

我正在尝试将 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/

有关java - 升级 Spring Security OAuth2的更多相关文章

  1. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过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

  2. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的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服务器更新战俘

  3. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用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

  4. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  5. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用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

  6. ruby - 在不使用 RVM 的情况下在 Mac 上卸载和升级 Ruby - 2

    我最近决定从我的系统中卸载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版本,并且我希望我的系统上只有一个版本。 最佳答案

  7. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  8. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  9. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  10. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

随机推荐