image.png

大概的流程图

基于内存存储令牌

首先创建一个父工程
并导入jar包

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.security.oauth.boot</groupId>
                <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                <version>2.0.6.RELEASE</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

然后在创建一个服务端,导入jar包

<properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <!-- Spring Security -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
    </dependencies>

image.png

创建好了之后大概的项目目录

在服务端创建一个客户端的配置文件

/**
 * 客户端
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    BCryptPasswordEncoder passwordEncoder;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // 配置客户端
        clients
                // 使用内存设置
                .inMemory()
                // client_id
                .withClient("client")
                // client_secret
                .secret(passwordEncoder.encode("secret"))
                // 授权类型
                .authorizedGrantTypes("authorization_code")
                // 授权范围
                .scopes("app")
                // 注册回调地址
                .redirectUris("https://www.asource.top");
    }
}

主要配置一些客户端的信息

然后创建一个Security的配置文件

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        PasswordEncoderFactories.createDelegatingPasswordEncoder();
        auth.inMemoryAuthentication()
                .withUser("user").password(passwordEncoder().encode("123")).roles("user")
                .and()
                .withUser("root").password(passwordEncoder().encode("123")).roles("root");
    }


}

主要就是模拟了两个账号

因为我们采用的是内存机制

然后重启项目访问获取授权码

http://localhost:8080/oauth/authorize?client_id=client&response_type=code

这个URL是固定的,一般只需要修改一下前面的请求地址就行

访问会直接进入登录
image.png

输入刚才配置好的账号密码登录

image.png

就可以进入授权页面选择Approve即可完成授权,就会自动跳转到指定的返回页面

image.png

并且能看到后面带的code

拿到code就可以使用postman进行测试向服务器申请令牌

通过 CURL 或是 Postman 请求

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'grant_type=authorization_code&code=1JuO6V' "http://client:secret@localhost:8080/oauth/token"

image.png

就能拿到从服务器获取的授权码

基于 JDBC 存储令牌

首先导入需要的jar包

	<!-- mybatis启动器 -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>

            <!-- mysql驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.32</version>
            </dependency>

            <!-- 通用Mapper启动器 -->
            <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.2</version>
            </dependency>

            <!-- 测试类 -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>

            <!-- 日志 -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>

配置数据源

spring:
  application:
    name: oauth2-server
  datasource:
    url: jdbc:mysql://localhost:3306/oauth2
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    hikari:
      maximum-pool-size: 30
      minimum-idle: 10
  thymeleaf:
    cache: false
server:
  port: 80

#日志打印
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

然后修改客户端配置

/**
 * 客户端
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    BCryptPasswordEncoder passwordEncoder;

    @Autowired
    DataSource dataSource;

    @Bean
    public TokenStore tokenStore() {
        // 基于 JDBC 实现,令牌保存到数据
        return new JdbcTokenStore(dataSource);
    }

    @Bean
    public ClientDetailsService jdbcClientDetails() {
        // 基于 JDBC 实现,需要事先在数据库配置客户端信息
        return new JdbcClientDetailsService(dataSource);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 设置令牌
        endpoints.tokenStore(tokenStore());
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // 读取客户端配置
        clients.withClientDetails(jdbcClientDetails());
    }
}

修改好了之后重启项目,再次访问获取授权码

http://localhost:8080/oauth/authorize?client_id=client&response_type=code

这个URL是固定的,一般只需要修改一下前面的请求地址就行

访问会直接进入登录
image.png

输入刚才配置好的账号密码登录

image.png

就可以进入授权页面选择Approve即可完成授权,就会自动跳转到指定的返回页面

image.png

并且能看到后面带的code

拿到code就可以使用postman进行测试向服务器申请令牌

通过 CURL 或是 Postman 请求

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'grant_type=authorization_code&code=1JuO6V' "http://client:secret@localhost:8080/oauth/token"

image.png

操作成功后数据库 oauth_access_token 表中会增加一笔记录,效果图如下:
image.png

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议