【问题标题】:Spring Security OAuth2 AuthorizationServerSpring Security OAuth2 授权服务器
【发布时间】:2015-05-22 19:13:18
【问题描述】:

我正在玩 spring-security-oauth2。我尝试使用身份验证后端构建一些微服务。

我建立了一个简单的spring boot项目,依赖如下

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.0.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

和一个配置类

@Configuration
public class SecurityConfiguration {

    @Autowired
    @Qualifier("clientDetailsServiceBean")
    private ClientDetailsService clientDetailsService;

    @Autowired
    @Qualifier("userDetailsServiceBean")
    private UserDetailsService userDetailsService;

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(jsr250Enabled = true, securedEnabled = true, prePostEnabled = true)
    public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

        @Override
        @Bean(name = "authenticationManagerBean")
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService);
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().permitAll().and().userDetailsService(userDetailsService).formLogin().and().httpBasic();
        }
    }

    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore());
        }

        @Bean
        public ApprovalStore approvalStore() throws Exception {
            TokenApprovalStore store = new TokenApprovalStore();
            store.setTokenStore(tokenStore());
            return store;
        }

        @Bean
        public TokenStore tokenStore() {
            return new InMemoryTokenStore();
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.withClientDetails(clientDetailsService);
        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            security.checkTokenAccess("permitAll()");
            security.allowFormAuthenticationForClients();
        }

    }

我的 Client- 和 UserDetailsS​​ervice 的实现非常简单,总是返回一个对象

@Service("clientDetailsServiceBean")
public class ClientDetailsServiceBean implements ClientDetailsService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ClientDetailsServiceBean.class);

    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
        LOGGER.info("Load client {}", clientId); 
        BaseClientDetails details = new BaseClientDetails();
        details.setClientId(clientId);
        details.setAuthorizedGrantTypes(Arrays.asList("password", "refresh_token", "client_credentials"));
        details.setScope(Arrays.asList("trust"));
        details.setAutoApproveScopes(Arrays.asList("trust"));
        details.setAuthorities(Arrays.asList(new SimpleGrantedAuthority("client_role2")));
        details.setResourceIds(Arrays.asList("clients"));
        details.setClientSecret("secret");

        return details;
    }

}
@Service("userDetailsServiceBean")
public class UserDetailsServiceBean implements UserDetailsService {
    private static final Logger LOGGER = LoggerFactory.getLogger(UserDetailsServiceBean.class);

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LOGGER.info("Load user {}", username);
        return new User(username, "password", Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")) );
    }
}

但是,当我尝试通过

接收访问令牌时
curl http://localhost:8081/oauth/token -d grant_type=client_credentials -d client_id=web_client -d client_secret=secret

我收到一个错误“访问此资源需要完全身份验证”,当我尝试时

curl http://localhost:8081/oauth/token -d grant_type=client_credentials -d client_id=web_client -d client_secret=secret --user web_client:secret

我收到错误“凭据错误”。从我的角度来看,两者都应该可以工作,但似乎我的配置丢失了。

OAuth 还有其他一些我不清楚的地方: 我尝试使用 spring-security 和自定义登录表单构建一个 spring-mvc 应用程序。是否可以通过 Spring Security 处理令牌请求和刷新周期而无需重定向到身份验证应用程序?

如果是事件驱动的应用程序,是否可以确保令牌有效?如果失败,用户单击按钮并写入事件,但处理将在数小时后完成。如何使用用户凭据处理事件?

【问题讨论】:

    标签: spring-security spring-security-oauth2 microservices


    【解决方案1】:

    您的内部 @Configuration 类必须是静态的。我很惊讶该应用程序完全启动了,而且您的整个SecurityConfiguration 可能实际上都没有被使用。

    是否可以通过 spring security 处理令牌请求和刷新周期而不重定向到身份验证应用程序?

    当然。您是否阅读了规范中的密码和 refresh_token 授权?但在 Web UI 中,强烈建议您使用授权码授权(带有重定向),以便用户只在受信任的地方输入他的凭据。

    用户单击按钮并写入事件,但处理将在数小时后完成。如何使用用户凭据处理事件?

    刷新令牌可能是最好的方法。该事件显然需要安全,因为它必须包含刷新令牌。

    【讨论】:

    • 谢谢你,在你的帮助下我发现我失败了。我们有多个 Web UI 产品,应该为我们的客户隐藏微服务基础设施。在 spring-security 或 spring-security-oauth2 中是否已经有一些实现,或者我必须为这种情况实现 AuthenticationProvider 和 Filter?
    • 我真的不知道。您必须解释“隐藏”的含义,而 stackoverflow 可能不是正确的地方。如果你想聊天,有一个 gitter.im 空间供 spring-security-oauth 使用。
    猜你喜欢
    • 2018-09-26
    • 2015-03-31
    • 2021-10-29
    • 2020-03-14
    • 2020-07-23
    • 2016-07-25
    • 1970-01-01
    • 2014-05-10
    • 2013-12-01
    相关资源
    最近更新 更多