使用 Spring OAuth2 的 Springboot [英] Springboot with Spring OAuth2

查看:59
本文介绍了使用 Spring OAuth2 的 Springboot的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Spring Boot 和 Spring Security OAuth 以及 JDBC 客户端支持在我的应用程序上实现 OAuth2.

我可以生成令牌,当我向 http://localhost:8080/oauth/token 发出 POST 请求时 我得到一个有效的回复,如:

<预><代码>{"access_token": "359e93b2-555a-477b-9a65-e5062314fc23","token_type": "承载","refresh_token": "6fd1ae31-8129-4729-a86b-e756c453a58a",expires_in":899,范围":阅读"}

现在奇怪的是,我在数据库中的任何地方都找不到这个令牌.如果我向/oauth/token 发出另一个请求,我会得到相同的令牌,但 expires_in 的值低于预期.我得出的结论是,这个令牌信息必须存储在某个地方,但我找不到.

01:24:41 SELECT * FROM dummy.oauth_access_token LIMIT 0, 1000 0 行返回 0.000 秒/0.000 秒

所有 OAuth 相关表都是空的,除了 oauth_client_details 具有生成令牌的客户端详细信息.

这是我的代码.

AuthServerOAuth2Config

@Configuration公共类 AuthServerOAuth2Config 扩展 AuthorizationServerConfigurerAdapter {私人最终 AuthenticationManager authenticationManager;私有最终 AppConfig appConfig;@自动连线公共 AuthServerOAuth2Config(AuthenticationManager authenticationManager, AppConfig appConfig) {this.authenticationManager = authenticationManager;this.appConfig = appConfig;}@覆盖公共无效配置(ClientDetailsS​​erviceConfigurer 客户端)抛出异常 {客户端.jdbc(appConfig.dataSource());}@覆盖public void configure(AuthorizationServerSecurityConfigurer security) 抛出异常 {security.checkTokenAccess("permitAll()");}@覆盖public void configure(AuthorizationServerEndpointsConfigurer endpoints) 抛出异常 {endpoints.authenticationManager(authenticationManager);}}

AppConfig 类

@Configuration@PropertySource(value = "classpath:application.properties")公共类 AppConfig {@Value("${spring.datasource.url}")私人字符串数据源网址;@Value("${spring.database.driverClassName}")私人字符串 dbDriverClassName;@Value("${spring.datasource.username}")私人字符串数据库用户名;@Value("${spring.datasource.password}")私人字符串dbPassword;@豆角,扁豆公共数据源数据源(){final DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName(dbDriverClassName);dataSource.setUrl(datasourceUrl);dataSource.setUsername(dbUsername);数据源.setPassword(dbPassword);返回数据源;}@豆角,扁豆公共令牌商店令牌商店(){返回新的 JdbcTokenStore(dataSource());}}

这是我的 pom.xml,以防它有助于找出数据库中没有持久化令牌的原因.

<groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.6.RELEASE</version><relativePath/><!-- 从存储库中查找父级 --></父母><属性><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><!-- 定义我们使用的是哪个版本的 Spring Framework --><spring-cloud.version>Dalston.SR1</spring-cloud.version></属性><依赖项><依赖><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></依赖><依赖><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><范围>测试</范围></依赖><依赖><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></依赖><依赖><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></依赖><依赖><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></依赖><依赖><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></依赖><依赖><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-aws-context</artifactId></依赖><依赖><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></依赖><依赖><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId></依赖><依赖><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.6.1</version></依赖><依赖><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.4.0</version></依赖><依赖><groupId>javax.validation</groupId><artifactId>validation-api</artifactId></依赖></依赖项>

我的问题是,为什么生成的令牌没有被持久化到 mysql 数据库中,我该如何解决?

解决方案

Spring Security OAuth 2 默认使用令牌存储的内存实现,参见 OAuth 2 开发人员指南:

<块引用>

在创建您的 AuthorizationServerTokenServices 实现时,您可能需要考虑使用 DefaultTokenServices,它具有许多可以插入以更改访问令牌的格式和存储的策略.默认情况下,它通过随机值创建令牌并处理除了它委托给 TokenStore 的令牌的持久性之外的所有内容.默认存储是内存中的实现,但还有一些其他实现可用.这是一个描述,并对其进行了一些讨论

  • 默认的 InMemoryTokenStore 非常适合单个服务器(即低流量且在出现故障时不会热插拔到备份服务器).大多数项目都可以从这里开始,也可能在开发模式下以这种方式运行,以便轻松启动没有依赖项的服务器.

您可以使用 AuthorizationServerEndpointsConfigurer#tokenStore.

您修改后的授权服务器端点配置:

@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) 抛出异常 {端点.authenticationManager(authenticationManager).tokenStore(appConfig.tokenStore());}

I'm implementing OAuth2 on my application using Spring Boot and Spring Security OAuth with JDBC client support.

I can generate tokens, when I make a POST request to http://localhost:8080/oauth/token I get a valid response like:

{
    "access_token": "359e93b2-555a-477b-9a65-e5062314fc23",
    "token_type": "bearer",
    "refresh_token": "6fd1ae31-8129-4729-a86b-e756c453a58a",
    "expires_in": 899,
    "scope": "read"
}

Now the strange this is, I cannot find this token anywhere in the database. If I make another request to /oauth/token I get the same token but with a lower value for expires_in as expected. I get to the conclusion that this token information must be stored somewhere but I can not find it.

01:24:41    SELECT * FROM dummy.oauth_access_token LIMIT 0, 1000    0 row(s) returned   0.000 sec / 0.000 sec

All OAuth related tables are empty except oauth_client_details which has the client details to generate the token.

Here's my code.

AuthServerOAuth2Config

@Configuration
public class AuthServerOAuth2Config extends AuthorizationServerConfigurerAdapter {

    private final AuthenticationManager authenticationManager;
    private final AppConfig appConfig;

    @Autowired
    public AuthServerOAuth2Config(AuthenticationManager authenticationManager, AppConfig appConfig) {
        this.authenticationManager = authenticationManager;
        this.appConfig = appConfig;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(appConfig.dataSource());
    }

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

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

AppConfig Class

@Configuration
@PropertySource(value = "classpath:application.properties")
public class AppConfig {

    @Value("${spring.datasource.url}")
    private String datasourceUrl;

    @Value("${spring.database.driverClassName}")
    private String dbDriverClassName;

    @Value("${spring.datasource.username}")
    private String dbUsername;

    @Value("${spring.datasource.password}")
    private String dbPassword;

    @Bean
    public DataSource dataSource() {
        final DriverManagerDataSource dataSource = new DriverManagerDataSource();

        dataSource.setDriverClassName(dbDriverClassName);
        dataSource.setUrl(datasourceUrl);
        dataSource.setUsername(dbUsername);
        dataSource.setPassword(dbPassword);

        return dataSource;
    }

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

And here's my pom.xml in case it is of any help to find why there are no tokens persisted in the database.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.6.RELEASE</version>
    <relativePath/>
    <!-- lookup parent from repository -->
</parent>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <!-- Defining which version of Spring Framework we are using -->
    <spring-cloud.version>Dalston.SR1</spring-cloud.version>
</properties>

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-aws-context</artifactId>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.6.1</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.4.0</version>
    </dependency>
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
    </dependency>
</dependencies>

My question is, why are the generated tokens not being persisted to the mysql database and how can I fix it?

解决方案

Spring Security OAuth 2 uses an in-memory implementation of the token store by default, see OAuth 2 Developers Guide:

When creating your AuthorizationServerTokenServices implementation, you may want to consider using the DefaultTokenServices which has many strategies that can be plugged in to change the format and storage of access tokens. By default it creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a TokenStore. The default store is an in-memory implementation, but there are some other implementations available. Here's a description with some discussion of each of them

  • The default InMemoryTokenStore is perfectly fine for a single server (i.e. low traffic and no hot swap to a backup server in the case of failure). Most projects can start here, and maybe operate this way in development mode, to make it easy to start a server with no dependencies.

You can change the used implementation of the token store with AuthorizationServerEndpointsConfigurer#tokenStore.

Your modified authorization server endpoint configuration:

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

这篇关于使用 Spring OAuth2 的 Springboot的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆